package com.niiwoo.civet.trade.service.local.lend;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dangdang.ddframe.rdb.sharding.api.HintManager;
import com.dangdang.ddframe.rdb.sharding.hint.HintManagerHolder;
import com.niiwoo.activity.stage.dto.request.inviteBuddy.ProjectStatusChangeEventDTO;
import com.niiwoo.activity.stage.dto.request.prize.ActiveInerestDiscountBackReqDTO;
import com.niiwoo.activity.stage.dto.request.prize.ActiveInerestRateReqDTO;
import com.niiwoo.activity.stage.dto.request.prize.ActiveInvestorCashBackReqDTO;
import com.niiwoo.activity.stage.dto.request.prize.ActiveLoanCashBackReqDTO;
import com.niiwoo.activity.stage.dto.request.project.ProjectRaiseRateInvestReqDTO;
import com.niiwoo.activity.stage.dto.request.rank.InvestRankNotifyRequestDTO;
import com.niiwoo.activity.stage.dto.response.prize.UserPrizeResponseDTO;
import com.niiwoo.activity.stage.enums.prize.ProjectRepaymentTypeEnum;
import com.niiwoo.activity.stage.enums.prize.UserPrizeTypeIdEnum;
import com.niiwoo.activity.stage.service.inviterBuddy.InviteBuddyActivityDubboService;
import com.niiwoo.activity.stage.service.prize.ActivityPrizeDubboService;
import com.niiwoo.activity.stage.service.project.ProjectRaiseRateDubboService;
import com.niiwoo.activity.stage.service.rank.InvestRankNotifyDubboService;
import com.niiwoo.asset.cardniu.dto.mq.CardNiuExternalMQConstants;
import com.niiwoo.asset.cardniu.dto.request.LoanStatusDTO;
import com.niiwoo.asset.constant.MqConstants;
import com.niiwoo.asset.org.business.constants.OrgRabbitConstant;
import com.niiwoo.asset.org.business.dto.mq.ProjectStatusChangeDTO;
import com.niiwoo.civet.account.dto.common.MoneyTotalDTO;
import com.niiwoo.civet.account.dto.common.ProjectInvestCustodyOrderDTO;
import com.niiwoo.civet.account.dto.common.sendmessage.LendSuccessBorrowerNotifyDTO;
import com.niiwoo.civet.account.dto.common.sendmessage.LendSuccessInvestorNotifyDTO;
import com.niiwoo.civet.account.dto.common.sendmessage.LendSuccessNotifyDTO;
import com.niiwoo.civet.account.dto.request.LendSuccessAccountingRequestDTO;
import com.niiwoo.civet.account.dto.response.AccountCompanyDTO;
import com.niiwoo.civet.account.dto.response.LendSuccessAccountingResponseDTO;
import com.niiwoo.civet.account.dto.response.WithdrawOrderResponseDTO;
import com.niiwoo.civet.account.enums.AccountAmountTypeEnum;
import com.niiwoo.civet.account.service.*;
import com.niiwoo.civet.account.service.lend.ProjectLendAccountingDubboService;
import com.niiwoo.civet.base.constant.OrgConstant;
import com.niiwoo.civet.base.enums.BorrowProjectTypeEnum;
import com.niiwoo.civet.base.enums.FeeTypeEnum;
import com.niiwoo.civet.trade.constant.AccountConfigConstants;
import com.niiwoo.civet.trade.constant.MqConstant;
import com.niiwoo.civet.trade.dao.entity.*;
import com.niiwoo.civet.trade.dao.mapper.*;
import com.niiwoo.civet.trade.dto.BorrowerRepaymentDTO;
import com.niiwoo.civet.trade.dto.ProjectBorrowerPlanNewDTO;
import com.niiwoo.civet.trade.dto.RateConfigDTO;
import com.niiwoo.civet.trade.dto.common.BathTransactionNotifyDTO;
import com.niiwoo.civet.trade.dto.common.BuildRepaymentDTO;
import com.niiwoo.civet.trade.dto.common.LendOrderDTO;
import com.niiwoo.civet.trade.dto.common.ProjectDynamicDTO;
import com.niiwoo.civet.trade.dto.request.contract.WithholdContractSignMQDTO;
import com.niiwoo.civet.trade.dto.request.databackflow.ProjectStatusChangeBackFlowRequestDTO;
import com.niiwoo.civet.trade.dto.request.loan.RepaymentPlanDTO;
import com.niiwoo.civet.trade.enums.*;
import com.niiwoo.civet.trade.enums.FadadaContractEnum.TradeTypeEnum;
import com.niiwoo.civet.trade.enums.FadadaContractTemplateEnum.TemplateTypeEnum;
import com.niiwoo.civet.trade.enums.ProjectStatusEnum;
import com.niiwoo.civet.trade.enums.ProjectTypeEnum;
import com.niiwoo.civet.trade.enums.RepaymentTypeEnum;
import com.niiwoo.civet.trade.service.databackflow.TianChengDataBackFlowDubboService;
import com.niiwoo.civet.trade.service.local.activity.ActivityEventService;
import com.niiwoo.civet.trade.service.local.contract.FadadaContractContext;
import com.niiwoo.civet.trade.service.local.intelligenceInvest.ProjectPackageLocalService;
import com.niiwoo.civet.trade.service.local.newRefund.common.RefundCommonService;
import com.niiwoo.civet.trade.service.local.plan.BorrowerInvestorRepaymentContext;
import com.niiwoo.civet.trade.service.local.project.ProjectLocalService;
import com.niiwoo.tripod.lanmao.component.LanMaoDirectService;
import com.niiwoo.tripod.lanmao.component.LanMaoSequence;
import com.niiwoo.tripod.lanmao.enums.*;
import com.niiwoo.tripod.lanmao.request.AsyncTransactionRequest;
import com.niiwoo.tripod.lanmao.request.ModifyProjectRequest;
import com.niiwoo.tripod.lanmao.request.QueryTransactionRequest;
import com.niiwoo.tripod.lanmao.response.AsyncTransactionResponse;
import com.niiwoo.tripod.lanmao.response.ModifyProjectResponse;
import com.niiwoo.tripod.lanmao.response.QueryTransactionResponse;
import com.niiwoo.tripod.provider.exception.BizException;
import com.niiwoo.tripod.service.component.SnowflakeIdWorker;
import com.niiwoo.tripod.tiancheng.component.TianchengDataFlowService;
import com.niiwoo.tripod.tiancheng.request.df.RepaymentPlanRequest;
import org.apache.commons.lang3.StringUtils;
import org.apache.curator.shaded.com.google.common.collect.Lists;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

@Service
public class ProjectLendLocalService {

	private static final Logger logger = LoggerFactory.getLogger(ProjectLendLocalService.class);

	@Autowired
	private ProjectMapperExt projectMapperExt;

	@Autowired
	private ProjectInvestOrderMapperExt projectInvestOrderMapperExt;

	@Autowired
	private SnowflakeIdWorker snowflakeIdWorker;

	@Autowired
	private LanMaoSequence lanMaoSequence;

	@Autowired
	private BorrowerInvestorRepaymentContext borrowerInvestorRepaymentContext;

	@Reference(version = "1.0.0")
	private AccountDubboService accountDubboService;

	@Reference(version = "1.0.0")
	private AccountInvestDubboService accountInvestDubboService;

	@Autowired
	private RabbitTemplate consistencyRabbitTemplate;

	@Autowired
	private ProjectRateMapperExt projectRateMapperExt;

	@Reference(version = "1.0.0")
	private InvestRankNotifyDubboService investRankNotifyDubboService;

	@Reference(version = "1.0.0")
	private InviteBuddyActivityDubboService inviteBuddyActivityDubboService;

	@Autowired
	private FadadaContractContext fadadaContractContext;

	@Autowired
	private ProjectContractMapperExt projectContractMapperExt;

	@Autowired
	private ProjectBorrowerPlanNewMapperExt projectBorrowerPlanNewMapperExt;

	@Autowired
	private TianchengDataFlowService dataFlowService;

	@Reference(version = "1.0.0")
	private ActivityPrizeDubboService activityPrizeDubboService;

	@Autowired
	private LanMaoDirectService lanMaoDirectService;

	@Autowired
	private ProjectLocalService projectLocalService;

	@Value("${h5-invest-detail-url}")
	private String h5InvestDetailUrl;

	@Value("${h5-borrow-detail-url}")
	private String h5BorrowDetailUrl;

	@Reference(version = "1.0.0")
	private MessageSendDubboService messageSendDubboService;

	@Reference(version = "1.0.0")
	private ProjectLendAccountingDubboService projectLendAccountingDubboService;

	@Autowired
	private LendOrderMapperExt lendOrderMapperExt;

	@Autowired
	private LendOrderDetailMapperExt lendOrderDetailMapperExt;

	@Autowired
	private LendOrderDetailBizMapperExt lendOrderDetailBizMapperExt;

	@Autowired
	private LendDataNotifyMapperExt lendDataNotifyMapperExt;

	@Autowired
	private LendInvestPrizeNotifyMapperExt lendInvestPrizeNotifyMapperExt;

	@Autowired
	private ActivityEventService activityEventService;

	@Autowired
	private ProjectInvestorPlanMapperExt projectInvestorPlanMapperExt;


    @Reference(version = "1.0.0")
    private TianChengDataBackFlowDubboService tianChengDataBackFlowDubboService;

	@Reference(version = "1.0.0")
	private WithdrawDubboService withdrawDubboService;
	
	@Reference(version = "1.0.0")
	private ProjectRaiseRateDubboService projectRaiseRateDubboService;

	@Reference(version = "1.0.0")
	private AccountCompanyDubboService accountCompanyDubboService;

	/**
	 * 银行存管业务明细最多支持90条
	 */
	private static final int MAX_DETAIL_NUM_TOTAL = 90;
	@Autowired
	private AdvanceConfigMapper advanceConfigMapperExt;
	@Autowired
	private RefundCommonService refundCommonService;
	@Autowired
	private AccountConfigMapper accountConfigMapper;

	@Autowired
	private ProjectPackageDetailMapperExt projectPackageDetailMapperExt;

	@Autowired
	private ProjectPackageMapperExt projectPackageMapperExt;

	@Autowired
	private ProjectPackageLocalService projectPackageLocalService;

	/**
	 * 生成放款订单
	 *
	 * @param projectId
	 * @return
	 */
	@Transactional
	public AsyncTransactionRequest buildLendOrder(Long projectId) {
		logger.info("生成放款订单 projectId:{}", projectId);
		Project project = projectMapperExt.selectByPrimaryKey(projectId);
		logger.info("生成放款订单 project:{}", JSON.toJSON(project));
		List<ProjectInvestOrder> projectInvestOrderList = projectInvestOrderMapperExt.queryProjectInvestOrderListOrderByCreateTimeAscByProjectId(projectId);
		Assert.notEmpty(projectInvestOrderList,"投资订单不存在，标的号="+projectId);
		Map<Long, String> investOrderIdRequestNoMap = queryInvestRequestNo(projectInvestOrderList);
		
		String batchNo = lanMaoSequence.getBatchNo();
		LendOrder lendOrder = new LendOrder();
		lendOrder.setProjectId(project.getProjectId());
		lendOrder.setBorrowUserId(project.getBorrowUserId());
		lendOrder.setBatchNo(batchNo);
		lendOrder.setCreateTime(new Date());
		lendOrder.setUpdateTime(new Date());
		lendOrderMapperExt.insertSelective(lendOrder);

		// 放款数据通知
		LendDataNotify lendDataNotify = new LendDataNotify();
		lendDataNotify.setProjectId(project.getProjectId());
		lendDataNotify.setCreateTime(new Date());
		lendDataNotify.setUpdateTime(new Date());
		lendDataNotifyMapperExt.insertSelective(lendDataNotify);

		// 放款订单明细
		LendOrderDetail lendOrderDetail = null;

		List<AsyncTransactionRequest.BizDetail> bizDetailList = new ArrayList<>();
		AsyncTransactionRequest.BizDetail bizDetail = null;
		List<AsyncTransactionRequest.BizDetail.BusinessDetail> businessDetailBizList = null;

		BigDecimal amountTotal = BigDecimal.ZERO;
		Integer numTotal = 0;
		for (ProjectInvestOrder projectInvestOrder : projectInvestOrderList) {
			if (projectInvestOrder != null && ProjectInvestOrderStatusEnum.SUCCESS.getValue().equals(projectInvestOrder.getStatus())) {
				if (investOrderIdRequestNoMap.get(projectInvestOrder.getId()) == null) {
					throw new BizException("TRD_700005", "投资订单对应银行存管requestNo为空，projectInvestOrderId:" + projectInvestOrder.getId());
				}
				if (MAX_DETAIL_NUM_TOTAL == numTotal) {
					lendOrderDetail.setAmountTotal(amountTotal);
					lendOrderDetail.setNumTotal(numTotal);
					lendOrderDetailMapperExt.insertSelective(lendOrderDetail);

					bizDetail.setDetails(businessDetailBizList);
					bizDetailList.add(bizDetail);

					amountTotal = BigDecimal.ZERO;
					numTotal = 0;
				}
				if (0 == numTotal) {
					lendOrderDetail = new LendOrderDetail();
					lendOrderDetail.setId(snowflakeIdWorker.nextId());
					lendOrderDetail.setBatchNo(batchNo);
					lendOrderDetail.setProjectId(project.getProjectId());
					lendOrderDetail.setDetailRequestNo(lanMaoSequence.getRequestNo());
					lendOrderDetail.setStatus(LendOrderStatusEnum.HANDLING.getValue());
					lendOrderDetail.setCreateTime(new Date());
					lendOrderDetail.setUpdateTime(new Date());

					bizDetail = new AsyncTransactionRequest.BizDetail();
					bizDetail.setRequestNo(lendOrderDetail.getDetailRequestNo());
					bizDetail.setTradeType(TransactionTypeEnum.TENDER);
					bizDetail.setProjectNo(project.getProjectId() + "");

					businessDetailBizList = new ArrayList<>();
				}

				// 放款订单业务明细
				LendOrderDetailBiz lendOrderDetailBiz = new LendOrderDetailBiz();
				lendOrderDetailBiz.setId(snowflakeIdWorker.nextId());
				lendOrderDetailBiz.setDetailRequestNo(lendOrderDetail.getDetailRequestNo());
				lendOrderDetailBiz.setBizType(BusinessTypeEnum.TENDER.getValue());
				lendOrderDetailBiz.setFreezeRequestNo(investOrderIdRequestNoMap.get(projectInvestOrder.getId()));
				lendOrderDetailBiz.setInvestOrderId(projectInvestOrder.getId());
				lendOrderDetailBiz.setSourceUserId(projectInvestOrder.getUserId());
				lendOrderDetailBiz.setSourceAccountId(projectInvestOrder.getAccountId());
				lendOrderDetailBiz.setSourcePlatformUserNo(projectInvestOrder.getPlatformUserNo());
				lendOrderDetailBiz.setTargetUserId(project.getBorrowUserId());
				lendOrderDetailBiz.setTargetAccountId(project.getBorrowAccountId());
				lendOrderDetailBiz.setTargetPlatformUserNo(project.getBorrowPlatformUserNo());
				lendOrderDetailBiz.setAmount(projectInvestOrder.getAmount());
				lendOrderDetailBiz.setCreateTime(new Date());
				lendOrderDetailBiz.setUpdateTime(new Date());
				lendOrderDetailBizMapperExt.insertSelective(lendOrderDetailBiz);

				// 放款投资红包通知
				if (projectInvestOrder.getPrizeId() != null) {
					LendInvestPrizeNotify lendInvestPrizeNotify = new LendInvestPrizeNotify();
					lendInvestPrizeNotify.setInvestOrderId(projectInvestOrder.getId());
					lendInvestPrizeNotify.setProjectId(project.getProjectId());
					lendInvestPrizeNotify.setCreateTime(new Date());
					lendInvestPrizeNotify.setUpdateTime(new Date());
					lendInvestPrizeNotifyMapperExt.insertSelective(lendInvestPrizeNotify);
				}
				
				AsyncTransactionRequest.BizDetail.BusinessDetail businessDetail = new AsyncTransactionRequest.BizDetail.BusinessDetail();
				BusinessTypeEnum bizType = BusinessTypeEnum.enumOf(lendOrderDetailBiz.getBizType());
				businessDetail.setBizType(bizType);
				businessDetail.setFreezeRequestNo(lendOrderDetailBiz.getFreezeRequestNo());
				businessDetail.setSourcePlatformUserNo(lendOrderDetailBiz.getSourcePlatformUserNo());
				businessDetail.setTargetPlatformUserNo(lendOrderDetailBiz.getTargetPlatformUserNo());
				businessDetail.setAmount(lendOrderDetailBiz.getAmount());

				businessDetailBizList.add(businessDetail);
				amountTotal = amountTotal.add(projectInvestOrder.getAmount());
				numTotal++;
			}
		}
		Assert.notNull(lendOrderDetail,"放款明细不可空");

		//前置平台管理费(5.3.0后置平台管理费取消节点放款时收取)
		if (/*ProjectFeeChargeNodeEnum.ManageFeeChargeNode.COLLECTION_OF_MONEY.getValue().equals(project.getManageFeeChargeNode()) &&
				project.getManageFee().compareTo(BigDecimal.ZERO) > 0*/
				project.getBeforeManageFee() != null && project.getBeforeManageFee().compareTo(BigDecimal.ZERO) > 0){
			LendOrderDetailBiz lendOrderDetailBiz = this.buildLendOrderDetailBizData(BusinessTypeEnum.COMMISSION,lendOrderDetail,project);
			AccountConfig accountConfig = accountConfigMapper.selectByPrimaryKey(AccountConfigConstants.getPlatform());
			lendOrderDetailBiz.setAmount(project.getBeforeManageFee());
			lendOrderDetailBiz.setFeeType(FeeTypeEnum.BEFORE_SEEK_MANAGEMENT_FEE.getValue());
			lendOrderDetailBiz.setTargetAccountId(accountConfig.getAccountId());
			lendOrderDetailBiz.setTargetPlatformUserNo(accountConfig.getPlatformUserNo());
			lendOrderDetailBiz.setTargetUserId(accountConfig.getUserId());
			lendOrderDetailBizMapperExt.insertSelective(lendOrderDetailBiz);
			businessDetailBizList.add(this.buidlBusinessDetailBizData(lendOrderDetailBiz));
		}

		//前置服务费
		if (project.getBeforeSeekAdviceServiceFee().compareTo(BigDecimal.ZERO) > 0) {
			AccountCompanyDTO accountCompanyDTO = refundCommonService.getConsultingByProject(project);
			LendOrderDetailBiz lendOrderDetailBiz = this.buildLendOrderDetailBizData(BusinessTypeEnum.PROFIT, lendOrderDetail, project);
			lendOrderDetailBiz.setAmount(project.getBeforeSeekAdviceServiceFee());
			lendOrderDetailBiz.setFeeType(FeeTypeEnum.BEFORE_SEEK_ADVICE_SERVICE_FEE.getValue());
			lendOrderDetailBiz.setTargetAccountId(accountCompanyDTO.getAccountId());
			lendOrderDetailBiz.setTargetPlatformUserNo(accountCompanyDTO.getAccountNo());
			lendOrderDetailBiz.setTargetUserId(accountCompanyDTO.getUserId());
			lendOrderDetailBizMapperExt.insertSelective(lendOrderDetailBiz);
			businessDetailBizList.add(this.buidlBusinessDetailBizData(lendOrderDetailBiz));
		}
		//后置咨询服务费
		if (ProjectFeeChargeNodeEnum.AfterSeekAdviceServiceFeeChargeNode.COLLECTION_OF_MONEY.getValue().equals(project.getAfterSeekAdviceServiceFeeChargeNode())
				&& project.getConsultingFee().compareTo(BigDecimal.ZERO) > 0){
			AccountCompanyDTO accountCompanyDTO = refundCommonService.getConsultingByProject(project);
			LendOrderDetailBiz lendOrderDetailBiz = this.buildLendOrderDetailBizData(BusinessTypeEnum.PROFIT, lendOrderDetail, project);
			lendOrderDetailBiz.setAmount(project.getConsultingFee());
			lendOrderDetailBiz.setFeeType(FeeTypeEnum.CONSULTING_FEE.getValue());
			lendOrderDetailBiz.setTargetAccountId(accountCompanyDTO.getAccountId());
			lendOrderDetailBiz.setTargetPlatformUserNo(accountCompanyDTO.getAccountNo());
			lendOrderDetailBiz.setTargetUserId(accountCompanyDTO.getUserId());
			lendOrderDetailBizMapperExt.insertSelective(lendOrderDetailBiz);

			businessDetailBizList.add(this.buidlBusinessDetailBizData(lendOrderDetailBiz));
		}
		//担保服务费
		if (ProjectFeeChargeNodeEnum.GuaranteeFeeChargeNode.COLLECTION_OF_MONEY.getValue().equals(project.getGuaranteeFeeChargeNode()) &&
				project.getGuaranteeFee().compareTo(BigDecimal.ZERO) > 0){
			AccountCompanyDTO guaranteeOrg = accountCompanyDubboService.getGuaranteeOrgByOrgId(project.getGuaranteeCompanyOrgId());
			if(guaranteeOrg == null){
				logger.error("放款构建订单处理异常 guaranteeOrg is null. projectId:{},guaranteeCompanyOrgId:{}", project.getProjectId(), project.getGuaranteeCompanyOrgId());
				throw new BizException("TRD10005", "放款构建订单处理异常 guaranteeOrg is null");
			}
			LendOrderDetailBiz lendOrderDetailBiz = this.buildLendOrderDetailBizData(BusinessTypeEnum.PROFIT, lendOrderDetail, project);
			lendOrderDetailBiz.setAmount(project.getGuaranteeFee());
			lendOrderDetailBiz.setFeeType(FeeTypeEnum.GUARANTEE_FEE.getValue());
			lendOrderDetailBiz.setTargetAccountId(guaranteeOrg.getAccountId());
			lendOrderDetailBiz.setTargetPlatformUserNo(guaranteeOrg.getAccountNo());
			lendOrderDetailBiz.setTargetUserId(project.getGuaranteeCompanyOrgId());
			lendOrderDetailBizMapperExt.insertSelective(lendOrderDetailBiz);

			businessDetailBizList.add(this.buidlBusinessDetailBizData(lendOrderDetailBiz));
		}


		lendOrderDetail.setAmountTotal(amountTotal);
		lendOrderDetail.setNumTotal(numTotal);
		lendOrderDetailMapperExt.insertSelective(lendOrderDetail);

		bizDetail.setDetails(businessDetailBizList);
		bizDetailList.add(bizDetail);

		// 银行存管业务明细
		AsyncTransactionRequest asyncTransactionRequest = new AsyncTransactionRequest();
		asyncTransactionRequest.setBatchNo(batchNo);
		asyncTransactionRequest.setBizDetails(bizDetailList);
		logger.info("放款订单构建成功 projectId:{}, asyncTransactionRequest:{}", projectId, JSON.toJSON(asyncTransactionRequest));
		return asyncTransactionRequest;
	}

	private LendOrderDetailBiz buildLendOrderDetailBizData(BusinessTypeEnum businessTypeEnum,LendOrderDetail lendOrderDetail,Project project){
		// 放款订单业务明细
		LendOrderDetailBiz lendOrderDetailBiz = new LendOrderDetailBiz();
		lendOrderDetailBiz.setId(snowflakeIdWorker.nextId());
		lendOrderDetailBiz.setDetailRequestNo(lendOrderDetail.getDetailRequestNo());
		lendOrderDetailBiz.setBizType(businessTypeEnum.getValue());
		//lendOrderDetailBiz.setFreezeRequestNo(investOrderIdRequestNoMap.get(projectInvestOrder.getId())); 可空
		//lendOrderDetailBiz.setInvestOrderId(-1L); 可空
		lendOrderDetailBiz.setSourceUserId(project.getBorrowUserId());
		lendOrderDetailBiz.setSourceAccountId(project.getBorrowAccountId());
		lendOrderDetailBiz.setSourcePlatformUserNo(project.getBorrowPlatformUserNo());

		lendOrderDetailBiz.setCreateTime(new Date());
		lendOrderDetailBiz.setUpdateTime(new Date());
		return lendOrderDetailBiz;
	}

	private AsyncTransactionRequest.BizDetail.BusinessDetail buidlBusinessDetailBizData(LendOrderDetailBiz lendOrderDetailBiz){
		AsyncTransactionRequest.BizDetail.BusinessDetail businessDetail = new AsyncTransactionRequest.BizDetail.BusinessDetail();
		BusinessTypeEnum bizType = BusinessTypeEnum.enumOf(lendOrderDetailBiz.getBizType());
		businessDetail.setBizType(bizType);
		businessDetail.setFreezeRequestNo(lendOrderDetailBiz.getFreezeRequestNo());
		businessDetail.setSourcePlatformUserNo(lendOrderDetailBiz.getSourcePlatformUserNo());
		businessDetail.setTargetPlatformUserNo(lendOrderDetailBiz.getTargetPlatformUserNo());
		businessDetail.setAmount(lendOrderDetailBiz.getAmount());
		return  businessDetail;
	}

	/**
	 * 放款结果通知
	 * @param lendNotifyDTOList
	 */
	public void lendResultNotify(List<BathTransactionNotifyDTO> lendNotifyDTOList){
		Assert.notNull(lendNotifyDTOList, "lendResultNotify lendNotifyDTOList is null.");
		for(BathTransactionNotifyDTO bathTransactionNotifyDTO : lendNotifyDTOList) {
			Assert.notNull(bathTransactionNotifyDTO, "lendResultNotify bathTransactionNotifyDTO is null.");
			logger.info("lendResultCallBack detailRequestNo:{}, bathTransactionNotifyDTO:{}", bathTransactionNotifyDTO.getAsyncRequestNo(), JSON.toJSON(bathTransactionNotifyDTO));
			((ProjectLendLocalService)AopContext.currentProxy()).lendResultNotify(bathTransactionNotifyDTO);
		}
	}

	@Transactional
	public void lendResultNotify(BathTransactionNotifyDTO bathTransactionNotifyDTO){
		LendOrderDetail lendOrderDetail = lendOrderDetailMapperExt.queryLendOrderDetailByDetailRequestNoForUpdate(bathTransactionNotifyDTO.getAsyncRequestNo());
		Assert.notNull(lendOrderDetail, "doLendResultCallBack lendResultCallBack is null, detailRequestNo=" + bathTransactionNotifyDTO.getAsyncRequestNo());
		if (!lendOrderDetail.getStatus().equals(LendOrderStatusEnum.HANDLING.getValue())) {
			// 订单状态已经被修改,此订单已经被处理过 后续操作中断
			logger.info("lendResultCallBack lendOrderDetail status not eq HANDLING. detailRequestNo:{}, status:{}", bathTransactionNotifyDTO.getAsyncRequestNo(), lendOrderDetail.getStatus());
			return;
		}
		logger.info("更新放款明细表状态 projectId:{}, detailRequestNo:{}, status:{}", lendOrderDetail.getProjectId(), bathTransactionNotifyDTO.getAsyncRequestNo(), bathTransactionNotifyDTO.getStatus());

		LendOrderDetail updateRecord = new LendOrderDetail();
		updateRecord.setId(lendOrderDetail.getId());
		updateRecord.setStatus(LendOrderStatusEnum.valueOf(bathTransactionNotifyDTO.getStatus()).getValue());
		if (LendOrderStatusEnum.FAIL.name().equals(bathTransactionNotifyDTO.getStatus())) {
			updateRecord.setErrorCode(bathTransactionNotifyDTO.getErrorCode());
			updateRecord.setErrorMessage(bathTransactionNotifyDTO.getErrorMessage());
		}
		lendOrderDetailMapperExt.updateByPrimaryKeySelective(updateRecord);

		if (LendOrderStatusEnum.FAIL.name().equals(bathTransactionNotifyDTO.getStatus())) {

			// 放款失败,终止后续操作
			logger.warn("银行存管返回状态为处理失败 bathTransactionNotifyDTO: {}", JSON.toJSON(bathTransactionNotifyDTO));
		} else if (LendOrderStatusEnum.SUCCESS.name().equals(bathTransactionNotifyDTO.getStatus())) {
			logger.info("接收到银行放款成功通知 projectId:{}; batchNo:{}; detailRequestNo:{}", lendOrderDetail.getProjectId(),
					lendOrderDetail.getBatchNo(), lendOrderDetail.getDetailRequestNo());

			int notSuccessNum = lendOrderDetailMapperExt.queryLendOrderDetailNotSuccessNumByProjectId(lendOrderDetail
					.getProjectId());
			logger.info("notSuccessNum:{};  projectId:{}; updateResult.getBatchNo():{}", notSuccessNum,
					lendOrderDetail.getProjectId(), lendOrderDetail.getBatchNo());
			// 全部放款成功
			if(notSuccessNum == 0){
				// 更新放款订单状态
				LendOrder lendOrder = new LendOrder();
				lendOrder.setProjectId(lendOrderDetail.getProjectId());
				lendOrder.setStatus(LendOrderStatusEnum.SUCCESS.getValue());
				lendOrder.setProjectChangeStatus(LendOrderStatusEnum.HANDLING.getValue()); // 标的变更状态修改为处理中
				lendOrder.setAccountingStatus(LendOrderStatusEnum.HANDLING.getValue()); // 记账状态修改为处理中
				lendOrder.setSuccessTime(new Date());
				lendOrderMapperExt.updateByPrimaryKeySelective(lendOrder);

				// 更新放款各个数据通知状态
				LendDataNotify lendDataNotify = new LendDataNotify();
				lendDataNotify.setProjectId(lendOrderDetail.getProjectId());
				lendDataNotify.setBorrowerPrizeStatus(LendOrderStatusEnum.HANDLING.getValue());
				lendDataNotify.setInvestorPrizeStatus(LendOrderStatusEnum.HANDLING.getValue());
				lendDataNotify.setRaiseRateStatus(LendOrderStatusEnum.HANDLING.getValue());
				lendDataNotify.setPackageRaiseRateStatus(LendOrderStatusEnum.HANDLING.getValue());
				lendDataNotify.setInvestRankStatus(LendOrderStatusEnum.HANDLING.getValue());
				lendDataNotify.setInviteBuddyStatus(LendOrderStatusEnum.HANDLING.getValue());
				lendDataNotify.setTianchengProjectStatus(LendOrderStatusEnum.HANDLING.getValue());
				lendDataNotify.setTianchengRepaymentPlanStatus(LendOrderStatusEnum.HANDLING.getValue());
				lendDataNotifyMapperExt.updateByPrimaryKeySelective(lendDataNotify);

                Project project = projectMapperExt.selectByPrimaryKey(lendOrderDetail.getProjectId());
                // 更新标的状态
                Project updateProjectRecord = new Project();
                updateProjectRecord.setProjectId(lendOrderDetail.getProjectId());
                updateProjectRecord.setStatus(ProjectStatusEnum.REPAYING.getStatus());
                updateProjectRecord.setSubStatus(ProjectSubStatusEnum.REPAYING_INIT.getSubStatus());
                updateProjectRecord.setUpdateTime(new Date());
                projectMapperExt.updateByPrimaryKeySelective(updateProjectRecord);

                // 记录标的动态信息
                ProjectDynamicDTO projectDynamicDTO = new ProjectDynamicDTO();
                projectDynamicDTO.setUserId(project.getBorrowUserId());
                projectDynamicDTO.setProjectId(project.getProjectId());
                projectDynamicDTO.setTradeTypeEnum(ProjectDynamicDTO.TradeTypeEnum.REPAYMENT);
                projectDynamicDTO.setProjectDynamicEnum(ProjectDynamicEnum.FULL_PROJECT_SUCCESS);
                projectLocalService.addProjectDynamicRecord(projectDynamicDTO);

                List<ProjectInvestOrder> projectInvestOrderList = projectInvestOrderMapperExt
                        .queryProjectInvestOrderListOrderByCreateTimeAscByProjectId(lendOrderDetail.getProjectId());

                for (ProjectInvestOrder projectInvestOrder : projectInvestOrderList) {
                    if (projectInvestOrder != null && ProjectInvestOrderStatusEnum.SUCCESS.getValue().equals(projectInvestOrder.getStatus())) {
						// 更新投资订单状态:回款中
                        ProjectInvestOrder updateProjectInvestOrderRecord = new ProjectInvestOrder();
                        updateProjectInvestOrderRecord.setId(projectInvestOrder.getId());
                        updateProjectInvestOrderRecord.setEvolutionStatus(ProjectInvestOrderEvolutionStatusEnum.BACKING.getValue());
						updateProjectInvestOrderRecord.setFullSuccessTime(project.getFullSuccessTime());
                        projectInvestOrderMapperExt.updateByPrimaryKeySelective(updateProjectInvestOrderRecord);

						// 更新放款投资红包通知状态：处理中
						if (projectInvestOrder.getPrizeId() != null) {
							LendInvestPrizeNotify lendInvestPrizeNotify = new LendInvestPrizeNotify();
							lendInvestPrizeNotify.setInvestOrderId(projectInvestOrder.getId());
							lendInvestPrizeNotify.setStatus(LendOrderStatusEnum.HANDLING.getValue());
							lendInvestPrizeNotifyMapperExt.updateByPrimaryKeySelective(lendInvestPrizeNotify);
						}
                    }
                }
                
				// 生成还款回款计划
				List<ProjectInvestorPlan> projectInvestorPlanList = buildBorrowerInvestorRepaymentPlan(project, projectInvestOrderList);

				projectPackageLocalService.projectFull(project.getProjectId());

				TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
					@Override
					public void afterCommit() {
						super.afterCommit();
						try {
							// 发送法大大合同签署消息
							consistencyRabbitTemplate.convertAndSend(MqConstant.PROJECT_LEND_CONTRACT_EXCHANGE,
									MqConstant.PROJECT_LEND_CONTRACT, project.getProjectId());
						}catch (Throwable e) {
							logger.error("发送法大大合同签署消息异常 projectId:{}", project.getProjectId(), e);
						}
						// 修改标的状态
						((ProjectLendLocalService)AopContext.currentProxy()).updateProjectStatus(project.getProjectId());

						((ProjectLendLocalService)AopContext.currentProxy()).handleLendOrderAfterSuccess(project, projectInvestOrderList, projectInvestorPlanList);
					}
				});
			}

		} else {
			// 放款通知状态异常。
			logger.error("放款通知状态异常 projectId:{}, bathTransactionNotifyDTO.getStatus():{}", lendOrderDetail.getProjectId(), bathTransactionNotifyDTO.getStatus());
			throw new BizException("ACC20004");
		}
	}

	/**
	 * 满标放款成功后续处理
	 * 
	 * @param project
	 * @param projectInvestOrderList
	 * @param projectInvestorPlanList
	 */
	@Transactional(propagation = Propagation.REQUIRES_NEW)
	public void handleLendOrderAfterSuccess(Project project, List<ProjectInvestOrder> projectInvestOrderList,
			List<ProjectInvestorPlan> projectInvestorPlanList) {
		// 放款成功记账
		try {
			lendSuccessAccounting(project, projectInvestorPlanList);
		}catch (Throwable e) {
			logger.error("放款成功记账异常 projectId:{}", project.getProjectId(), e);
		}

		// 放款数据通知
		lendDataNotify(project, projectInvestOrderList, projectInvestorPlanList);

		// 发送放款成功通知
		try {
			sendMessageAndStandLetter(project.getProjectId());
		}catch (Throwable e) {
			logger.error("发送放款成功通知异常 projectId:{}", project.getProjectId(), e);
		}
	}

	/**
	 * 根据提现订单ID查询放款订单
	 *
	 * @param withdrawOrderId
	 * @return
	 */
	public LendOrderDTO queryLendOrderByWithdrawOrderId(Long withdrawOrderId) {
		LendOrderDTO result = null;
		LendOrder lendOrder = lendOrderMapperExt.queryLendOrderByWithdrawOrderId(withdrawOrderId);
		if (lendOrder != null) {
			result = new LendOrderDTO();
			BeanUtils.copyProperties(lendOrder, result);
		}
		return result;
	}

	/**
	 * 放款合同处理
	 *
	 * @param projectId
	 */
	public void lendContractHandler(Long projectId) throws Exception {
		String bizContractNo = "b_" + projectId;
		Project project = projectMapperExt.selectByPrimaryKey(projectId);

		if(project == null){
			logger.error("放款合同处理处理异常 project is null. projectId:{}", projectId);
			throw new BizException("TRD10005", "放款合同处理处理异常 project is null");
		}

		if(!ProjectStatusEnum.REPAYING.getStatus().equals(project.getStatus()) && !ProjectStatusEnum.FINISH.getStatus().equals(project.getStatus())){
			logger.error("放款合同处理处理异常 project status is not 3 . project:{}", JSON.toJSONString(project));
			throw new BizException("TRD10005", "放款合同处理处理异常 标状态不为还款中");
		}

		if(BorrowProjectTypeEnum.ORG_SPEEDLOAN_NEW.getValue().equals(project.getType())
				|| BorrowProjectTypeEnum.DECORATION_LOAN.getValue().equals(project.getType())){
			try {
				logger.info("机构标签署代扣协议 projectId:{}, type:{}", projectId, project.getType());
				WithholdContractSignMQDTO withholdContractSignMQDTO = new WithholdContractSignMQDTO();
				withholdContractSignMQDTO.setUserId(project.getBorrowUserId());
				withholdContractSignMQDTO.setProjectId(projectId);
				logger.info("机构标签署代扣协议 withholdContractSignMQDTO:{}"+JSON.toJSONString(withholdContractSignMQDTO));
				consistencyRabbitTemplate.convertAndSend(MqConstant.FADADA_CONTRACT_EXCHANGE, MqConstant.FADADA_WITHHOLD_CONTRACT_ROUTE, withholdContractSignMQDTO);
			}catch (Throwable e) {
				logger.error("发送机构标签署代扣协议消息异常 projectId:{}", project.getProjectId(), e);
			}
		}

		// 借款合同
		if((BorrowProjectTypeEnum.ORG_SPEEDLOAN_NEW.getValue().equals(project.getType())) && !OrgConstant.NIWOTA_ORG_ID.equals(project.getOrgId())
				&& !LoanTypeEnum.BUSINESS_LOAN.getValue().equals(project.getLoanType())){//鸿特/俊拓
			if(OrgConstant.JUNTUO_ORG_ID.equals(project.getOrgId()) && PeriodUnitEnum.DAY.getValue().equals(project.getDeadlineUnit())){
				if (BorrowerTypeEnum.COMPANY.getType().equals(project.getBorrowerType())) {
					//俊拓企业
					ProjectContract fastLoanInitContract = projectContractMapperExt.queryProjectContractByProjectIdAndContractType(projectId, TemplateTypeEnum.JUN_TUO_COMPANY_FAST_LOAN.getType());
					if (fastLoanInitContract == null) {
						fastLoanInitContract = fadadaContractContext.initContractRecord(projectId,
								project.getBorrowUserId(), bizContractNo, TemplateTypeEnum.JUN_TUO_COMPANY_FAST_LOAN.getType(),
								TradeTypeEnum.LOAN.getType(), projectId);
						((ProjectLendLocalService) AopContext.currentProxy()).saveLendContractInitData(fastLoanInitContract);
					}

					if (StringUtils.isBlank(fastLoanInitContract.getViewUrl()) && StringUtils.isBlank(fastLoanInitContract.getDownloadUrl())) {
						ProjectContract fastLoanSignContract = fadadaContractContext.contractHandler(TemplateTypeEnum.JUN_TUO_COMPANY_FAST_LOAN,
								bizContractNo, project, null);
						fastLoanSignContract.setId(fastLoanInitContract.getId());
						((ProjectLendLocalService) AopContext.currentProxy()).updateProjectContract(fastLoanSignContract);
					}
				} else {
					//俊拓个人
					ProjectContract fastLoanInitContract = projectContractMapperExt.queryProjectContractByProjectIdAndContractType(projectId, TemplateTypeEnum.JUN_TUO_PERSONAL_FAST_LOAN.getType());
					if (fastLoanInitContract == null) {
						fastLoanInitContract = fadadaContractContext.initContractRecord(projectId,
								project.getBorrowUserId(), bizContractNo, TemplateTypeEnum.JUN_TUO_PERSONAL_FAST_LOAN.getType(),
								TradeTypeEnum.LOAN.getType(), projectId);
						((ProjectLendLocalService) AopContext.currentProxy()).saveLendContractInitData(fastLoanInitContract);
					}

					if (StringUtils.isBlank(fastLoanInitContract.getViewUrl()) && StringUtils.isBlank(fastLoanInitContract.getDownloadUrl())) {
						ProjectContract fastLoanSignContract = fadadaContractContext.contractHandler(TemplateTypeEnum.JUN_TUO_PERSONAL_FAST_LOAN,
								bizContractNo, project, null);
						fastLoanSignContract.setId(fastLoanInitContract.getId());
						((ProjectLendLocalService) AopContext.currentProxy()).updateProjectContract(fastLoanSignContract);
					}
				}
			} else {
				if (BorrowerTypeEnum.COMPANY.getType().equals(project.getBorrowerType())) {
					//鸿特企业
					ProjectContract fastLoanInitContract = projectContractMapperExt.queryProjectContractByProjectIdAndContractType(projectId, TemplateTypeEnum.ORG_COMPANY_FAST_LOAN.getType());
					if (fastLoanInitContract == null) {
						fastLoanInitContract = fadadaContractContext.initContractRecord(projectId,
								project.getBorrowUserId(), bizContractNo, TemplateTypeEnum.ORG_COMPANY_FAST_LOAN.getType(),
								TradeTypeEnum.LOAN.getType(), projectId);
						((ProjectLendLocalService) AopContext.currentProxy()).saveLendContractInitData(fastLoanInitContract);
					}

					if (StringUtils.isBlank(fastLoanInitContract.getViewUrl()) && StringUtils.isBlank(fastLoanInitContract.getDownloadUrl())) {
						ProjectContract fastLoanSignContract = fadadaContractContext.contractHandler(TemplateTypeEnum.ORG_COMPANY_FAST_LOAN,
								bizContractNo, project, null);
						fastLoanSignContract.setId(fastLoanInitContract.getId());
						((ProjectLendLocalService) AopContext.currentProxy()).updateProjectContract(fastLoanSignContract);
					}
				} else {
					//鸿特个人
					ProjectContract fastLoanInitContract = projectContractMapperExt.queryProjectContractByProjectIdAndContractType(projectId, TemplateTypeEnum.ORG_PERSONAL_FAST_LOAN.getType());
					if (fastLoanInitContract == null) {
						fastLoanInitContract = fadadaContractContext.initContractRecord(projectId,
								project.getBorrowUserId(), bizContractNo, TemplateTypeEnum.ORG_PERSONAL_FAST_LOAN.getType(),
								TradeTypeEnum.LOAN.getType(), projectId);
						((ProjectLendLocalService) AopContext.currentProxy()).saveLendContractInitData(fastLoanInitContract);
					}

					if (StringUtils.isBlank(fastLoanInitContract.getViewUrl()) && StringUtils.isBlank(fastLoanInitContract.getDownloadUrl())) {
						ProjectContract fastLoanSignContract = fadadaContractContext.contractHandler(TemplateTypeEnum.ORG_PERSONAL_FAST_LOAN,
								bizContractNo, project, null);
						fastLoanSignContract.setId(fastLoanInitContract.getId());
						((ProjectLendLocalService) AopContext.currentProxy()).updateProjectContract(fastLoanSignContract);
					}
				}
			}
		} else if(BorrowProjectTypeEnum.DECORATION_LOAN.getValue().equals(project.getType())){
			//土巴兔
			ProjectContract fastLoanInitContract = projectContractMapperExt.queryProjectContractByProjectIdAndContractType(projectId, TemplateTypeEnum.TO8TO_FAST_LOAN.getType());
			if (fastLoanInitContract == null) {
				fastLoanInitContract = fadadaContractContext.initContractRecord(projectId,
						project.getBorrowUserId(), bizContractNo, TemplateTypeEnum.TO8TO_FAST_LOAN.getType(),
						TradeTypeEnum.LOAN.getType(), projectId);
				((ProjectLendLocalService) AopContext.currentProxy()).saveLendContractInitData(fastLoanInitContract);
			}

			if (StringUtils.isBlank(fastLoanInitContract.getViewUrl()) && StringUtils.isBlank(fastLoanInitContract.getDownloadUrl())) {
				ProjectContract fastLoanSignContract = fadadaContractContext.contractHandler(TemplateTypeEnum.TO8TO_FAST_LOAN,
						bizContractNo, project, null);
				fastLoanSignContract.setId(fastLoanInitContract.getId());
				((ProjectLendLocalService) AopContext.currentProxy()).updateProjectContract(fastLoanSignContract);
			}
		} else {
			// 你我他还需要签署的协议
			// INFORMATION_INQUIRY_AUTHORIZATION((byte)26,"信息查询授权书"),
			//        INFORMATION_CONSULTING_SERVICE_PROTOCOL((byte)27,"信息咨询服务协议"),
			if(OrgConstant.NIWOTA_ORG_ID.equals(project.getOrgId())){
				ProjectContract informationInquiryAuthorization = projectContractMapperExt.queryProjectContractByProjectIdAndContractType(projectId, TemplateTypeEnum.INFORMATION_INQUIRY_AUTHORIZATION.getType());
				if(informationInquiryAuthorization == null) {
					informationInquiryAuthorization = fadadaContractContext.initContractRecord(projectId,
							project.getBorrowUserId(), bizContractNo, TemplateTypeEnum.INFORMATION_INQUIRY_AUTHORIZATION.getType(),
							TradeTypeEnum.LOAN.getType(), projectId);
					((ProjectLendLocalService)AopContext.currentProxy()).saveLendContractInitData(informationInquiryAuthorization);
				}

				if(StringUtils.isBlank(informationInquiryAuthorization.getViewUrl()) && StringUtils.isBlank(informationInquiryAuthorization.getDownloadUrl())) {
					ProjectContract signContract = fadadaContractContext.contractHandler(TemplateTypeEnum.INFORMATION_INQUIRY_AUTHORIZATION,
							bizContractNo, project, null);
					signContract.setId(informationInquiryAuthorization.getId());
					((ProjectLendLocalService) AopContext.currentProxy()).updateProjectContract(signContract);
				}

				ProjectContract informationConsultingServiceProtocol = projectContractMapperExt.queryProjectContractByProjectIdAndContractType(projectId, TemplateTypeEnum.INFORMATION_CONSULTING_SERVICE_PROTOCOL.getType());
				if(informationConsultingServiceProtocol == null) {
					informationConsultingServiceProtocol = fadadaContractContext.initContractRecord(projectId,
							project.getBorrowUserId(), bizContractNo, TemplateTypeEnum.INFORMATION_CONSULTING_SERVICE_PROTOCOL.getType(),
							TradeTypeEnum.LOAN.getType(), projectId);
					((ProjectLendLocalService)AopContext.currentProxy()).saveLendContractInitData(informationConsultingServiceProtocol);
				}

				if(StringUtils.isBlank(informationConsultingServiceProtocol.getViewUrl()) && StringUtils.isBlank(informationConsultingServiceProtocol.getDownloadUrl())) {
					ProjectContract signContract = fadadaContractContext.contractHandler(TemplateTypeEnum.INFORMATION_CONSULTING_SERVICE_PROTOCOL,
							bizContractNo, project, null);
					signContract.setId(informationConsultingServiceProtocol.getId());
					((ProjectLendLocalService) AopContext.currentProxy()).updateProjectContract(signContract);
				}
			}
			ProjectContract fastLoanInitContract = projectContractMapperExt.queryProjectContractByProjectIdAndContractType(projectId, TemplateTypeEnum.FAST_LOAN.getType());
			if(fastLoanInitContract == null) {
				fastLoanInitContract = fadadaContractContext.initContractRecord(projectId,
						project.getBorrowUserId(), bizContractNo, TemplateTypeEnum.FAST_LOAN.getType(),
						TradeTypeEnum.LOAN.getType(), projectId);
				((ProjectLendLocalService)AopContext.currentProxy()).saveLendContractInitData(fastLoanInitContract);
			}

			if(StringUtils.isBlank(fastLoanInitContract.getViewUrl()) && StringUtils.isBlank(fastLoanInitContract.getDownloadUrl())) {
				ProjectContract fastLoanSignContract = fadadaContractContext.contractHandler(TemplateTypeEnum.FAST_LOAN,
						bizContractNo, project, null);
				fastLoanSignContract.setId(fastLoanInitContract.getId());
				((ProjectLendLocalService) AopContext.currentProxy()).updateProjectContract(fastLoanSignContract);
			}
		}

		// 征信查询授权书
        ProjectContract creditEnquiryInitContract = projectContractMapperExt
				.queryProjectContractByProjectIdAndContractType(projectId, TemplateTypeEnum.CREDIT_ENQUIRY_AUTHORIZATION.getType());
        if(creditEnquiryInitContract == null) {
			creditEnquiryInitContract = fadadaContractContext.initContractRecord(projectId,
                    project.getBorrowUserId(), bizContractNo, TemplateTypeEnum.CREDIT_ENQUIRY_AUTHORIZATION.getType(),
                    TradeTypeEnum.LOAN.getType(), projectId);
            ((ProjectLendLocalService)AopContext.currentProxy()).saveLendContractInitData(creditEnquiryInitContract);
        }

        if(StringUtils.isBlank(creditEnquiryInitContract.getViewUrl()) && StringUtils.isBlank(creditEnquiryInitContract.getDownloadUrl())) {
            ProjectContract creditEnquirySignContract = fadadaContractContext.contractHandler(TemplateTypeEnum.CREDIT_ENQUIRY_AUTHORIZATION,
                    bizContractNo, project, project.getBorrowUserId());
			creditEnquirySignContract.setId(creditEnquiryInitContract.getId());
            ((ProjectLendLocalService) AopContext.currentProxy()).updateProjectContract(creditEnquirySignContract);
        }

	}

	@Transactional
	public void updateProjectContract(ProjectContract projectContract) {
		projectContractMapperExt.updateByPrimaryKeySelective(projectContract);
	}

	@Transactional
	public void saveLendContractInitData(ProjectContract projectContract) {
		projectContractMapperExt.insertSelective(projectContract);
	}


	/**
	 * 生成还款回款计划
	 * @param projectId
	 * @return
	 */
	@Transactional
	public List<ProjectInvestorPlan> buildBorrowerRepaymentPlan(Long projectId) {
		Project project = projectMapperExt.selectByPrimaryKey(projectId);
		List<ProjectRate> projectRateList = projectRateMapperExt
				.queryProjectRateListOrderByCurrentPeriodAscByProjectIdAndBorrowUserId(projectId,
						project.getBorrowUserId());

		BuildRepaymentDTO buildRepaymentDTO = new BuildRepaymentDTO();
		buildRepaymentDTO.setRepaymentType(RepaymentTypeEnum.enumOf(project.getRepaymentType()));
		buildRepaymentDTO.setPeriodUnit(PeriodUnitEnum.enumOf(project.getDeadlineUnit()));
		buildRepaymentDTO.setDeadline(project.getDeadline());
		buildRepaymentDTO.setYearRate(project.getBorrowRate());
		buildRepaymentDTO.setAmount(project.getContractAmount());
		buildRepaymentDTO.setManageRate(project.getManageRate());
		buildRepaymentDTO.setGuaranteeRate(project.getGuaranteeRate());

		List<RateConfigDTO> rateConfigDTOList = new ArrayList<RateConfigDTO>();
		for (ProjectRate projectRate : projectRateList) {
			RateConfigDTO rateConfigDTO = new RateConfigDTO();
			BeanUtils.copyProperties(projectRate, rateConfigDTO);
			rateConfigDTOList.add(rateConfigDTO);
		}
		List<ProjectInvestOrder> projectInvestOrderList = projectInvestOrderMapperExt
				.queryProjectInvestOrderListOrderByCreateTimeAscByProjectId(project.getProjectId());
		BorrowerRepaymentDTO borrowerRepaymentDTO = borrowerInvestorRepaymentContext.buildBorrowerRepaymentPlan(
				project, projectRateList);
		// 生成投资人回款计划
		return borrowerInvestorRepaymentContext.buildInvestorRepaymentPlan(project, projectInvestOrderList,
				borrowerRepaymentDTO);

	}

	public List<RepaymentPlanDTO> getBorrowerRepaymentPlan(Long projectId) {
		Project project = projectMapperExt.selectByPrimaryKey(projectId);
		List<ProjectRate> projectRateList = projectRateMapperExt
				.queryProjectRateListOrderByCurrentPeriodAscByProjectIdAndBorrowUserId(projectId,
						project.getBorrowUserId());

		BuildRepaymentDTO buildRepaymentDTO = new BuildRepaymentDTO();
		buildRepaymentDTO.setRepaymentType(RepaymentTypeEnum.enumOf(project.getRepaymentType()));
		buildRepaymentDTO.setPeriodUnit(PeriodUnitEnum.enumOf(project.getDeadlineUnit()));
		buildRepaymentDTO.setDeadline(project.getDeadline());
		buildRepaymentDTO.setYearRate(project.getBorrowRate());
		buildRepaymentDTO.setAmount(project.getContractAmount());
		buildRepaymentDTO.setManageRate(project.getManageRate());
		buildRepaymentDTO.setGuaranteeRate(project.getGuaranteeRate());

		List<RateConfigDTO> rateConfigDTOList = new ArrayList<RateConfigDTO>();
		for (ProjectRate projectRate : projectRateList) {
			RateConfigDTO rateConfigDTO = new RateConfigDTO();
			BeanUtils.copyProperties(projectRate, rateConfigDTO);
			rateConfigDTOList.add(rateConfigDTO);
		}
		return borrowerInvestorRepaymentContext.getBorrowerRepaymentPlan(
				buildRepaymentDTO, rateConfigDTOList);
	}

	/**
	 * 生成还款回款计划
	 * @param project
	 * @param projectInvestOrderList
	 * @return
	 */
	@Transactional
	public List<ProjectInvestorPlan> buildBorrowerInvestorRepaymentPlan(Project project, List<ProjectInvestOrder> projectInvestOrderList) {
		List<ProjectRate> projectRateList = projectRateMapperExt
				.queryProjectRateListOrderByCurrentPeriodAscByProjectIdAndBorrowUserId(project.getProjectId(),
						project.getBorrowUserId());
		// 生成借款人还款计划
		BorrowerRepaymentDTO borrowerRepaymentDTO = borrowerInvestorRepaymentContext.buildBorrowerRepaymentPlan(
				project, projectRateList);
		// 生成投资人回款计划
		return borrowerInvestorRepaymentContext.buildInvestorRepaymentPlan(project, projectInvestOrderList,
				borrowerRepaymentDTO);
	}

	/**
	 * 查询投资订单银行存管流水号
	 *
	 * @param projectInvestOrderList
	 * @return
	 */
	public Map<Long, String> queryInvestRequestNo(List<ProjectInvestOrder> projectInvestOrderList) {
		Map<Long, String> result = new HashMap<>();
		Set<Long> investOrderIdSet = new HashSet<>();
		for (ProjectInvestOrder projectInvestOrder : projectInvestOrderList) {
			if (projectInvestOrder != null
					&& ProjectInvestOrderStatusEnum.SUCCESS.getValue().equals(projectInvestOrder.getStatus())) {
				investOrderIdSet.add(projectInvestOrder.getId());
			}
		}
		logger.info("queryInvestRequestNo investOrderIdSet.size() : {}", investOrderIdSet.size());

		List<ProjectInvestCustodyOrderDTO> projectInvestCustodyOrderDTOList = accountInvestDubboService
				.queryProjectInvestCustodyOrderListByInvestOrderIdSet(investOrderIdSet);
		if (projectInvestCustodyOrderDTOList != null) {
			for (ProjectInvestCustodyOrderDTO projectInvestCustodyOrderDTO : projectInvestCustodyOrderDTOList) {
				if (projectInvestCustodyOrderDTO != null) {
					result.put(projectInvestCustodyOrderDTO.getInvestOrderId(),
							projectInvestCustodyOrderDTO.getRequestNo());
				}
			}
		}
		logger.info("queryInvestRequestNo result.size() : {}", result.size());

		return result;
	}


	/**
	 * 调用银行存管放款
	 *
	 * @param asyncTransactionRequest
	 */
	@Transactional( propagation = Propagation.REQUIRES_NEW)
	public void callBankLend(AsyncTransactionRequest asyncTransactionRequest) {
		Long projectId = null;
		for (AsyncTransactionRequest.BizDetail bizDetail : asyncTransactionRequest.getBizDetails()) {
			projectId = Long.parseLong(bizDetail.getProjectNo());
		}
		logger.info("调用银行存管放款 projectId:{}", projectId);

		CompletableFuture<AsyncTransactionResponse> future = null;
		try {
			// 调用银行存管放款
			future = lanMaoDirectService.asyncTransaction(asyncTransactionRequest);
		} catch (Throwable e) {
			logger.error("调用银行存管批量放款异常 projectId:{}", projectId, e);
			throw e;
		}

		try {
			AsyncTransactionResponse response = future.get();
			if(response != null && !"100001".equals(response.getErrorCode())) {
				logger.info("调用银行存管批量放款结果 projectId:{}, response:{}", projectId, JSON.toJSON(response));
				if (ResponseCodeEnum.FAILURE.getValue().equals(response.getCode())) {// 调用失败
					((ProjectLendLocalService) AopContext.currentProxy()).callBankLendBackFailUpdateLendOrderStatus(asyncTransactionRequest, response.getErrorCode(), response.getErrorMessage());
					logger.error("调用银行存管批量放款失败 projectId:{}; errorMessage : {}", projectId, response.getErrorMessage());
					throw new BizException("ACC20002", "调用银行存管批量放款失败:" + response.getErrorMessage());
				} else {
					if (ResponseStatusEnum.INIT.getValue().equals(response.getStatus())) {// 处理失败
						((ProjectLendLocalService) AopContext.currentProxy()).callBankLendBackFailUpdateLendOrderStatus(asyncTransactionRequest, response.getErrorCode(), response.getErrorMessage());
						logger.error("调用银行存管批量放款失败 projectId:{}; errorMessage : {}", projectId, response.getErrorMessage());
						throw new BizException("ACC20001", "调用银行存管批量放款,银行返回业务处理失败:" + response.getErrorMessage());
					} else if (ResponseStatusEnum.SUCCESS.getValue().equals(response.getStatus())) {
						logger.info("调用银行存管放款成功 projectId:{}", projectId);
					}
				}
			} else {
				logger.warn("调用银行存管批量放款异常 projectId:{}, response:{}", projectId, JSON.toJSON(response));
			}
		} catch (InterruptedException | ExecutionException e) {
			logger.error("调用银行存管批量放款异常 projectId:{}", projectId, e);
			throw new BizException("ACC20003", "调用银行存管批量放款异常");
		}
	}

	/**
	 * 调用银行放款明确返回失败修改订单状态
	 * @param asyncTransactionRequest
	 * @param errorCode
	 * @param errorMessage
	 */
	@Transactional
	public void callBankLendBackFailUpdateLendOrderStatus(AsyncTransactionRequest asyncTransactionRequest, String errorCode, String errorMessage){
		for(AsyncTransactionRequest.BizDetail bizDetail : asyncTransactionRequest.getBizDetails()){
            LendOrderDetail lendOrderDetail = lendOrderDetailMapperExt.queryLendOrderDetailByDetailRequestNoForUpdate(bizDetail.getRequestNo());
			LendOrderDetail updateRecord = new LendOrderDetail();
			updateRecord.setId(lendOrderDetail.getId());
			updateRecord.setStatus(LendOrderStatusEnum.FAIL.getValue());
			updateRecord.setErrorCode(errorCode);
			updateRecord.setErrorMessage(errorMessage);
			lendOrderDetailMapperExt.updateByPrimaryKeySelective(updateRecord);
		}
	}

	/**
	 * 查询银行放款结果
	 *
	 * @param detailRequestNo
	 * @param projectId
	 * @return
	 */
	private BathTransactionNotifyDTO queryBankLendResult(String detailRequestNo, Long projectId) {
		logger.info("调用银行查询标的放款结果 projectId:{}", projectId);
		CompletableFuture<QueryTransactionResponse> future = null;
		try {
			QueryTransactionRequest request = new QueryTransactionRequest();
			request.setRequestNo(detailRequestNo);
			request.setTransactionType(TradeQueryTypeEnum.TRANSACTION);
			future = lanMaoDirectService.queryTransaction(request);
		} catch (Throwable e) {
			logger.error("调用银行存管查询交易结果异常 projectId:{}", projectId, e);
			throw new BizException("ACC20009", e.getMessage());
		}

		try {
			QueryTransactionResponse response = future.get();
			logger.info("查询标的银行放款结果 projectId:{}; response:{}", projectId, JSON.toJSON(response));
			if (ResponseCodeEnum.SUCCESS.getValue().equals(response.getCode())) {
				List<QueryTransactionResponse.TransactionDetail> records = response.getRecords();
				if (records == null || records.isEmpty() || records.get(0) == null) {
					throw new BizException("ACC20009", "调用银行存管查询交易结果失败:" + response.getErrorMessage());
				}
				BathTransactionNotifyDTO result = new BathTransactionNotifyDTO();
				result.setAsyncRequestNo(detailRequestNo);

				TransationStatusEnum status = TransationStatusEnum.enumOf(records.get(0).getStatus());
				switch (status) {
					case SUCCESS:
						result.setStatus(LendOrderStatusEnum.SUCCESS.name());
						return result;
					case FAIL:
						logger.warn("查询标的银行放款结果 银行存管返回状态为处理失败  projectId:{}, records.get(0): {}", projectId, JSON.toJSON(records.get(0)));
						result.setStatus(LendOrderStatusEnum.FAIL.name());
						result.setErrorCode(records.get(0).getErrorCode());
						result.setErrorMessage(records.get(0).getErrorMessage());
						return result;
					case ERROR:
						logger.warn("查询标的银行放款结果 银行存管返回状态为处理异常  projectId:{}, records.get(0): {}", projectId, JSON.toJSON(records.get(0)));
						result.setStatus(LendOrderStatusEnum.FAIL.name());
						result.setErrorCode(records.get(0).getErrorCode());
						result.setErrorMessage(records.get(0).getErrorMessage());
						return result;
					default:
						logger.info("查询标的银行放款结果 银行存管返回状态为处理中  projectId:{}, records.get(0): {}", projectId, JSON.toJSON(records.get(0)));
						throw new BizException("ACC20010", "调用银行存管查询交易结果,银行返回处理中:" + response.getErrorMessage());
				}
			} else {
				// 100007 查询对象不存在，需要重新发起放款
				if ("100007".equals(response.getErrorCode())) {
					logger.error("查询标的银行放款结果不存在 projectId:{}; response:{}", projectId, JSON.toJSON(response));
					((ProjectLendLocalService)AopContext.currentProxy()).orderNotFound(detailRequestNo, response.getErrorCode(), response.getErrorMessage());
					throw new BizException("ACC20008", "查询标的银行放款结果不存在:" + response.getErrorMessage());
				} else {
					// 调用查询失败
					logger.error("查询标的银行放款结果失败 projectId:{}; response:{}", projectId, JSON.toJSON(response));
					throw new BizException("ACC20009", "调用银行存管查询交易结果失败:" + response.getErrorMessage());
				}
			}
		} catch (InterruptedException e) {
			logger.error("调用银行存管查询交易结果异常 projectId:{}", projectId, e);
			throw new BizException("ACC20011", "调用银行存管查询交易结果异常");
		} catch (ExecutionException e) {
			logger.error("调用银行存管查询交易结果异常 projectId:{}", projectId, e);
			throw new BizException("ACC20011", "调用银行存管查询交易结果异常");
		}
	}

	/**
	 * 订单不存在修改订单明细状态
	 *
	 * @param detailRequestNo
	 * @param errorCode
	 * @param errorMessage
	 */
	@Transactional
	public void orderNotFound(String detailRequestNo, String errorCode, String errorMessage){
		LendOrderDetail lendOrderDetail = lendOrderDetailMapperExt.queryLendOrderDetailByDetailRequestNoForUpdate(detailRequestNo);
		if(lendOrderDetail.getCreateTime().before(new DateTime().minusMinutes(20).toDate())){
			LendOrderDetail updateRecord = new LendOrderDetail();
			updateRecord.setId(lendOrderDetail.getId());
			updateRecord.setStatus(LendOrderStatusEnum.FAIL.getValue());
			updateRecord.setErrorCode(errorCode);
			updateRecord.setErrorMessage(errorMessage);
			lendOrderDetailMapperExt.updateByPrimaryKeySelective(updateRecord);
		}
	}

	/**
	 * 更新银行存管标的状态
	 * @param projectId
	 */
	public void updateProjectStatus(Long projectId) {
		try {
			ProjectLendLocalService projectLendLocalService = ((ProjectLendLocalService)AopContext.currentProxy());
			projectLendLocalService.updateBankProjectStatus(projectId);
			projectLendLocalService.updateProjectStatusSuccessful(projectId);
		} catch (Throwable e) {
			logger.error("修改银行存管标的状态异常 projectId:{}", projectId, e);
		}
	}

	/**
	 * 标的状态更新成功
	 * @param projectId
	 */
	@Transactional(propagation = Propagation.REQUIRES_NEW)
	public void updateProjectStatusSuccessful(Long projectId){
		logger.info("更新标的状态成功,更新订单标的更新状态 projectId:{}", projectId);
		LendOrder lendOrder = new LendOrder();
		lendOrder.setProjectId(projectId);
		lendOrder.setProjectChangeStatus(LendOrderStatusEnum.SUCCESS.getValue());
		int num = lendOrderMapperExt.updateByPrimaryKeySelective(lendOrder);
		logger.info("更新标的状态成功,更新订单标的更新状态 projectId:{},num={}", projectId, num);
	}

	/**
	 * 更新标的状态
	 *
	 * @param projectId
	 */
	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public void updateBankProjectStatus(Long projectId) {
		logger.info("更新标的状态 projectId:{}", projectId);
		CompletableFuture<ModifyProjectResponse> future = null;
		try {
			// 调用银行存款修改标的状态为回款中。
			ModifyProjectRequest request = new ModifyProjectRequest();
			request.setRequestNo(lanMaoSequence.getRequestNo());
			request.setProjectNo(projectId + "");
			request.setStatus(com.niiwoo.tripod.lanmao.enums.ProjectStatusEnum.REPAYING);
			future = lanMaoDirectService.modifyProject(request);
		} catch (Throwable e) {
			logger.error("调用银行存管修改标的状态异常 projectId:{}", projectId, e);
			throw e;
		}

		try {
			ModifyProjectResponse response = future.get();
			logger.info("调用银行存管修改标的状态结果 projectId:{}; response:{}", projectId, JSON.toJSON(response));
			if (ResponseCodeEnum.FAILURE.getValue().equals(response.getCode())) {// 调用失败
                logger.error("调用银行存管修改标的状态失败 projectId:{}; errorMessage : {}", projectId, response.getErrorMessage());
                throw new BizException("ACC20006", "调用银行存管修改标的状态失败:" + response.getErrorMessage());
			} else {
                if (ResponseStatusEnum.INIT.getValue().equals(response.getStatus())) {// 处理失败
                    logger.error("调用银行存管修改标的状态失败 projectId:{}; errorMessage:{}", projectId, response.getErrorMessage());
                    throw new BizException("ACC20005", "银行存管修改标的状态,银行返回处理失败 :" + response.getErrorMessage());
                } else if (ResponseStatusEnum.SUCCESS.getValue().equals(response.getStatus())) {
                    logger.info("更新标的状态成功 projectId:{}", projectId);
                }
			}
		} catch (InterruptedException | ExecutionException e) {
			logger.error("调用银行存管修改标的状态异常 projectId:{}", projectId, e);
			throw new BizException("ACC20007", "调用银行存管修改标的状态异常");
		}
	}

	/**
	 * 放款成功记账操作
	 * @param project
	 * @param projectInvestorPlanList
	 */
	private void lendSuccessAccounting(Project project, List<ProjectInvestorPlan> projectInvestorPlanList){
		logger.info("放款处理成功， projectId:{}", project.getProjectId());
		LendSuccessAccountingRequestDTO requestDTO = new LendSuccessAccountingRequestDTO();
		Long borrowerAccountId = project.getBorrowAccountId();
		Map<String, Long> investorAccountMap = new HashMap<>();
		List<LendSuccessAccountingRequestDTO.InvestSuccessBill> investSuccessBillList = new ArrayList<>();
		List<MoneyTotalDTO> investTotal = new ArrayList<>();
		List<MoneyTotalDTO> investFreeze = new ArrayList<>();
		List<LendOrderDetailBiz> lendOrderDetailBizList = lendOrderDetailBizMapperExt.queryLendOrderDetailBizByProjectId(project.getProjectId());
		for (LendOrderDetailBiz lendOrderDetailBiz : lendOrderDetailBizList) {
			if(FeeTypeEnum.CAPITAL.getValue().equals(lendOrderDetailBiz.getFeeType())){
				investorAccountMap.put(lendOrderDetailBiz.getSourceUserId(), lendOrderDetailBiz.getSourceAccountId());
				// 投资人账单
				LendSuccessAccountingRequestDTO.InvestSuccessBill  investSuccessBill = new LendSuccessAccountingRequestDTO.InvestSuccessBill();
				investSuccessBill.setUserId(lendOrderDetailBiz.getSourceUserId());
				investSuccessBill.setInvestOrderId(lendOrderDetailBiz.getInvestOrderId());
				investSuccessBillList.add(investSuccessBill);

				// 投资人投资金额累计
				MoneyTotalDTO investTotalMoneyTotalDTO = new MoneyTotalDTO();
				investTotalMoneyTotalDTO.setAmount(lendOrderDetailBiz.getAmount());
				investTotalMoneyTotalDTO.setAmountType(AccountAmountTypeEnum.INVEST_TOTAL);
				investTotalMoneyTotalDTO.setAccountId(lendOrderDetailBiz.getSourceAccountId());
				investTotal.add(investTotalMoneyTotalDTO);

				// 投资人投资冻结金额释放
				MoneyTotalDTO investFreezeMoneyTotalDTO = new MoneyTotalDTO();
				investFreezeMoneyTotalDTO.setAmountType(AccountAmountTypeEnum.INVEST_FREEZE);
				investFreezeMoneyTotalDTO.setAmount(lendOrderDetailBiz.getAmount().negate());
				investFreezeMoneyTotalDTO.setAccountId(lendOrderDetailBiz.getSourceAccountId());
				investFreeze.add(investFreezeMoneyTotalDTO);
			} else if(FeeTypeEnum.BEFORE_SEEK_MANAGEMENT_FEE.getValue().equals(lendOrderDetailBiz.getFeeType())){
				requestDTO.setManagementFee(lendOrderDetailBiz.getAmount());
				requestDTO.setManagemenAccountId(lendOrderDetailBiz.getTargetAccountId());
			} else if(FeeTypeEnum.GUARANTEE_FEE.getValue().equals(lendOrderDetailBiz.getFeeType())){
				requestDTO.setGuaranteeFee(lendOrderDetailBiz.getAmount());
				requestDTO.setGuaranteeAccountId(lendOrderDetailBiz.getTargetAccountId());
			} else if(FeeTypeEnum.CONSULTING_FEE.getValue().equals(lendOrderDetailBiz.getFeeType())){
				requestDTO.setConsultingFee(lendOrderDetailBiz.getAmount());
				requestDTO.setConsultingAccountId(lendOrderDetailBiz.getTargetAccountId());
			} else if(FeeTypeEnum.BEFORE_SEEK_ADVICE_SERVICE_FEE.getValue().equals(lendOrderDetailBiz.getFeeType())){
				requestDTO.setBeforeSeekAdviceServiceFee(lendOrderDetailBiz.getAmount());
				requestDTO.setBeforeSeekAdviceServiceAccountId(lendOrderDetailBiz.getTargetAccountId());
			}
		}

		// 待收本息
		List<MoneyTotalDTO> dueInCapitalInterest = new ArrayList<>();
		for (ProjectInvestorPlan projectInvestorPlan : projectInvestorPlanList){
			MoneyTotalDTO dueInCorpus = new MoneyTotalDTO();
			dueInCorpus.setAccountId(investorAccountMap.get(projectInvestorPlan.getUserId()));
			dueInCorpus.setAmountType(AccountAmountTypeEnum.DUE_IN_CORPUS);
			dueInCorpus.setAmount(projectInvestorPlan.getCapital());

			MoneyTotalDTO dueInInterest = new MoneyTotalDTO();
			dueInInterest.setAccountId(investorAccountMap.get(projectInvestorPlan.getUserId()));
			dueInInterest.setAmountType(AccountAmountTypeEnum.DUE_IN_INTEREST);
			dueInInterest.setAmount(projectInvestorPlan.getInterest());

			dueInCapitalInterest.add(dueInCorpus);
			dueInCapitalInterest.add(dueInInterest);
		}

		// 借款账单
		List<LendOrderDetail> lendOrderDetailList = lendOrderDetailMapperExt.queryLendOrderDetailByProjectId(project.getProjectId());

		requestDTO.setProjectId(project.getProjectId());
		requestDTO.setFromSource(project.getFromSource());
		requestDTO.setProjectType(project.getType());
		requestDTO.setBorrowerUserId(project.getBorrowUserId());
		requestDTO.setBorrowMobile(project.getBorrowMobile());
		requestDTO.setBorrowAmount(project.getContractAmount());
		requestDTO.setBorrowerAccountId(borrowerAccountId);
		requestDTO.setRequestNo(lendOrderDetailList.get(0).getDetailRequestNo());

		// 借款金额累计
		MoneyTotalDTO borrowTotalMoneyTotalDTO = new MoneyTotalDTO();
		borrowTotalMoneyTotalDTO.setAccountId(borrowerAccountId);
		borrowTotalMoneyTotalDTO.setAmountType(AccountAmountTypeEnum.BORROW_TOTAL);
		borrowTotalMoneyTotalDTO.setAmount(project.getContractAmount());

		requestDTO.setBorrowTotal(borrowTotalMoneyTotalDTO);
		requestDTO.setInvestTotal(investTotal);
		requestDTO.setInvestFreeze(investFreeze);
		requestDTO.setDueInCapitalInterest(dueInCapitalInterest);
		requestDTO.setInvestSuccessBillList(investSuccessBillList);

		requestDTO.setIsPackagedProject(projectPackageLocalService.isPackagedProject(project.getProjectId()));

		LendSuccessAccountingResponseDTO responseDTO = projectLendAccountingDubboService.lendSuccessAccounting(requestDTO);
		if(responseDTO != null){
			logger.info("调用账务中心记账成功 projectId:{}", project.getProjectId());
			((ProjectLendLocalService)AopContext.currentProxy()).updateLendAccountingSuccessful(project.getProjectId(), responseDTO.getWithdrawOrderId());
		}
	}

	/**
	 * 更新放款记账成功
	 * @param projectId
	 * @param withdrawOrderId
	 */
	@Transactional
	public void updateLendAccountingSuccessful(Long projectId, Long withdrawOrderId){
		logger.info("调用账务中心记账成功，更新记账状态 projectId:{}", projectId);
		LendOrder lendOrder = new LendOrder();
		lendOrder.setProjectId(projectId);
		lendOrder.setWithdrawOrderId(withdrawOrderId);
		lendOrder.setAccountingStatus(LendOrderStatusEnum.SUCCESS.getValue());
		int num = lendOrderMapperExt.updateByPrimaryKeySelective(lendOrder);
		logger.info("调用账务中心记账成功，更新记账状态成功 projectId:{}, num={}",num);
	}
	
	/**
	 * 满标放款数据通知
	 * 
	 * @param project
	 * @param projectInvestOrderList
	 * @param projectInvestorPlanList
	 */
	private void lendDataNotify(Project project, List<ProjectInvestOrder> projectInvestOrderList, List<ProjectInvestorPlan> projectInvestorPlanList) {
		logger.info("放款数据通知 projectId:{}", project.getProjectId());
		// 满标借款通知
		activityEventService.fullBorrowEventNotify(project.getProjectId());

		// 满标投资通知
		activityEventService.investEventNotify(project.getProjectId());

		try {
			investRankNotify(project.getProjectId());
			((ProjectLendLocalService)AopContext.currentProxy()).updateInvestRankNotifySuccessful(project.getProjectId());
		} catch (Throwable e) {
			logger.error("投资排行榜通知异常 projectId:{}", project.getProjectId(), e);
		}

		try {
			prizeHandler(project, projectInvestorPlanList);
		} catch (Throwable e) {
			logger.error("放款红包处理异常 projectId:{}", project.getProjectId(), e);
		}
		
		try {
			projectRaiseRateHandle(project, projectInvestOrderList);
		} catch (Throwable e) {
			logger.error("放款运营投资加息活动处理异常 projectId:{}", project.getProjectId(), e);
		}

		try {
			packageRaiseRateHandle(project, projectInvestOrderList);
		} catch (Throwable e) {
			logger.error("放款包运营投资加息活动处理异常 projectId:{}", project.getProjectId(), e);
		}
		
		try {
			repaymentPlanDataFlow(project);
			((ProjectLendLocalService)AopContext.currentProxy()).updateTianChengRepaymentPlanNotifySuccessful(project.getProjectId());
		} catch (Throwable e) {
			logger.error("天秤数据回流异常 projectId:{}", project.getProjectId(), e);
		}
		try {
			projectStatusChange(project.getProjectId(), project.getFullSuccessTime());
			((ProjectLendLocalService)AopContext.currentProxy()).updateTianChengProjectStatusNotifySuccessful(project.getProjectId());
		} catch (Throwable e) {
			logger.error("标的状态变更通知天秤异常 projectId:{}", project.getProjectId(), e);
		}
		try {
			inviteBestirActivitySuccessProject(project);
			((ProjectLendLocalService)AopContext.currentProxy()).updateInviteBuddyNotifySuccessful(project.getProjectId());
		} catch (Throwable e) {
			logger.error("邀请好友投资借款满标数据统计异常 projectId{}", project.getProjectId(), e);
		}

		try {
			if (project != null && project.getFromSource() == ProjectFromSourceEnum.CARD_NIU.getType().byteValue()) {
				LoanStatusDTO loanStatusDTO = new LoanStatusDTO();
				loanStatusDTO.setProjectId(project.getProjectId());
				loanStatusDTO.setStatus((byte) 3);
				loanStatusDTO.setSubStatus(300);
				loanStatusDTO.setType(com.niiwoo.civet.trade.enums.ProjectTypeEnum.CARD_NIU_LOAN.getValue());
				logger.info("send CARD_NIU LoanStatusDTO:{}", JSON.toJSON(loanStatusDTO));
				consistencyRabbitTemplate.convertAndSend(CardNiuExternalMQConstants.Exchange.LOAN_STATUS_EXCHANGE,
						CardNiuExternalMQConstants.getRoutingKey(CardNiuExternalMQConstants.Exchange.LOAN_STATUS_EXCHANGE, CardNiuExternalMQConstants.Queue.LOAN_STATUS_QUEUE), loanStatusDTO);
			}
		} catch (Throwable e) {
			logger.error("send CARD_NIU LoanStatusDTO异常 projectId:{}", project.getProjectId(), e);
		}

		try {
			if (project != null && BorrowProjectTypeEnum.ORG_SPEEDLOAN_NEW.getValue().equals(project.getType())
					|| BorrowProjectTypeEnum.DECORATION_LOAN.getValue().equals(project.getType())) {
				ProjectStatusChangeDTO projectStatusChangeDTO = new ProjectStatusChangeDTO();
				projectStatusChangeDTO.setProjectId(project.getProjectId());
				logger.info("send ORG_SPEEDLOAN_NEW LoanStatusDTO:{}", JSON.toJSON(projectStatusChangeDTO));
				consistencyRabbitTemplate.convertAndSend(OrgRabbitConstant.Exchange.ORG_COMMON_DIRECT_EXCHANGE,
						CardNiuExternalMQConstants.getRoutingKey(OrgRabbitConstant.Exchange.ORG_COMMON_DIRECT_EXCHANGE, OrgRabbitConstant.Queue.PROJECT_STATUS_CHANGE_NOTIFY_QUEUE), projectStatusChangeDTO);
			}
		} catch (Throwable e) {
			logger.error("send ORG_SPEEDLOAN_NEW LoanStatusDTO异常 projectId:{}", project.getProjectId(), e);
		}


		// 融360标的还款计划生成发送通知
		try {
			if (project != null && project.getFromSource() == ProjectFromSourceEnum.R360.getType().byteValue()) {
				Map<String, Long> map = new HashMap<>();
				map.put("projectId", project.getProjectId());
				Message msg = new Message(JSON.toJSONString(map).getBytes(Charset.forName("UTF-8")), null);
				consistencyRabbitTemplate.send(MqConstants.Exchange.ASSET_EXCHANGE, MqConstants.getRoutingKey(
						MqConstants.Exchange.ASSET_EXCHANGE, MqConstants.Queue.REPAYMENT_PLAN_PUSH), msg);
			}
		} catch (Throwable e) {
			logger.error("融360标的还款计划生成发送通知异常 projectId:{}", project.getProjectId(), e);
		}

//        if (project != null && project.getFromSource() == ProjectFromSourceEnum.HUIJIE.getType().byteValue()) {
//            try {
//                HuijieOrderStatusChangedDTO huijieOrderStatusChangedDTO = new HuijieOrderStatusChangedDTO();
//                huijieOrderStatusChangedDTO.setProjectId(project.getProjectId());
//                huijieOrderStatusChangedDTO.setHuijieOrderProjectSubStatusEnum(HuijieOrderProjectSubStatusEnum.REPAYING_INIT);
//                huijieOrderStatusChangedDTO.setHuijieOrderStatusEnum(HuijieOrderStatusEnum.REPAYING);
//                huijieOrderStatusChangedDTO.setReason("放款成功通知");
//                huijieOrderStatusChangedDTO.setUpdateDate(new Date());
//                logger.info("send huijie_order_status_nofify huijieOrderStatusChangedDTO:{}", JSON.toJSON(huijieOrderStatusChangedDTO));
//                consistencyRabbitTemplate.convertAndSend(HuijieMqConstants.Exchange.ASSET_HUIJIE_EXCHANGE,
//                        HuijieMqConstants.getRoutingKey(HuijieMqConstants.Exchange.ASSET_HUIJIE_EXCHANGE, HuijieMqConstants.Queue.ORDER_STATUS_NOFIFY_QUEUE), huijieOrderStatusChangedDTO);
//            } catch (Throwable e) {
//                logger.error("汇介标发送订单状态反馈mq异常，send huijie_order_status_nofify projectId:{}", project.getProjectId(), e);
//            }
//
//            try {
//                logger.info("send huijie_repayment_plan_push_nofify projectId:{}", JSON.toJSON(project.getProjectId()));
//                consistencyRabbitTemplate.convertAndSend(HuijieMqConstants.Exchange.ASSET_HUIJIE_EXCHANGE,
//                        HuijieMqConstants.getRoutingKey(HuijieMqConstants.Exchange.ASSET_HUIJIE_EXCHANGE, HuijieMqConstants.Queue.REPAYMENT_PLAN_PUSH), project.getProjectId());
//            } catch (Throwable e) {
//                logger.error("汇介标还款计划推送mq发送异常，send huijie_repayment_plan_push_nofify projectId:{}", project.getProjectId(), e);
//            }
//        }
	}

	/**
	 * 邀请好友投资借款满标数据统计
	 * 
	 * @param project
	 */
	private void inviteBestirActivitySuccessProject(Project project) {
		logger.info("邀请好友投资借款满标数据统计开始...");
		ProjectTypeEnum investType = ProjectTypeEnum.getEnum(project.getType());
		if (ProjectTypeEnum.ORG_SPEEDLOAN.equals(investType) || ProjectTypeEnum.PERSONAL_SPEEDLOAN.equals(investType)) {
			ProjectStatusChangeEventDTO projectStatusChangeEventDTO = new ProjectStatusChangeEventDTO();
			projectStatusChangeEventDTO.setProjectId(project.getProjectId());
			projectStatusChangeEventDTO.setUserId(project.getBorrowUserId());
			projectStatusChangeEventDTO
					.setProjectType(ProjectTypeEnum.ORG_SPEEDLOAN.equals(investType) ? com.niiwoo.activity.stage.enums.inviterBuddy.ProjectTypeEnum.CONSUMEPTION_LOAD
							: com.niiwoo.activity.stage.enums.inviterBuddy.ProjectTypeEnum.SPEED_LOAD);
			projectStatusChangeEventDTO.setDateTime(project.getFullSuccessTime());

			RpcContext.getContext().asyncCall(
					() -> inviteBuddyActivityDubboService
							.inviteBestirActivitySuccessProject(projectStatusChangeEventDTO));
		}
		logger.info("邀请好友投资借款满标数据统计结束...");
	}

	/**
	 * 更新邀请好友借款通知成功
	 * @param projectId
	 */
	@Transactional
	public void updateInviteBuddyNotifySuccessful(Long projectId){
		LendDataNotify lendDataNotify = new LendDataNotify();
		lendDataNotify.setProjectId(projectId);
		lendDataNotify.setInviteBuddyStatus(LendOrderStatusEnum.SUCCESS.getValue());
		lendDataNotifyMapperExt.updateByPrimaryKeySelective(lendDataNotify);
	}

	/**
	 * 投资排行榜通知
	 * 
	 * @param projectId
	 */
	private void investRankNotify(Long projectId) {
		logger.info("投资排行榜通知 projectId:{}", projectId);
		Project project = projectMapperExt.selectByPrimaryKey(projectId);
		List<ProjectInvestOrder> projectInvestOrderList = projectInvestOrderMapperExt
				.queryProjectInvestOrderListOrderByCreateTimeAscByProjectId(project.getProjectId());
		for (ProjectInvestOrder projectInvestOrder : projectInvestOrderList) {
			if (projectInvestOrder != null
					&& ProjectInvestOrderStatusEnum.SUCCESS.getValue().equals(projectInvestOrder.getStatus())) {

				InvestRankNotifyRequestDTO investRankNotifyRequestDTO = new InvestRankNotifyRequestDTO();
				investRankNotifyRequestDTO.setUserId(projectInvestOrder.getUserId());
				investRankNotifyRequestDTO.setProjectId(project.getProjectId());
				investRankNotifyRequestDTO.setProjectName(project.getTitle());
				investRankNotifyRequestDTO.setFullDate(project.getFullSuccessTime());
				investRankNotifyRequestDTO.setInvestorId(projectInvestOrder.getId());
				investRankNotifyRequestDTO.setDeadLine(project.getDeadline());
				investRankNotifyRequestDTO.setInvestDate(projectInvestOrder.getCreateTime());
				investRankNotifyRequestDTO.setInvestAmount(projectInvestOrder.getAmount());
				investRankNotifyRequestDTO.setInvestProfit(projectInvestOrder.getInterest());
				investRankNotifyRequestDTO.setProjectType((int) project.getType());

				investRankNotifyDubboService.notify(investRankNotifyRequestDTO);
			}
		}
		logger.info("投资排行榜通知结束...");
	}

	/**
	 * 更新投资排行通知成功
	 * @param projectId
	 */
	@Transactional
	public void updateInvestRankNotifySuccessful(Long projectId){
		LendDataNotify lendDataNotify = new LendDataNotify();
		lendDataNotify.setProjectId(projectId);
		lendDataNotify.setInvestRankStatus(LendOrderStatusEnum.SUCCESS.getValue());
		lendDataNotifyMapperExt.updateByPrimaryKeySelective(lendDataNotify);
	}

    /**
     * 标的状态变更通知天秤
     *
     * @param projectId
	 * @param fullSuccessTime
     */
    private void projectStatusChange(Long projectId, Date fullSuccessTime) {
        ProjectStatusChangeBackFlowRequestDTO projectStatusChangeBackFlowRequestDTO = new ProjectStatusChangeBackFlowRequestDTO();
        projectStatusChangeBackFlowRequestDTO.setProjectId(projectId);
        projectStatusChangeBackFlowRequestDTO.setFromStatus("200");
        projectStatusChangeBackFlowRequestDTO.setStatus("300");
		projectStatusChangeBackFlowRequestDTO.setFullTime((fullSuccessTime.getTime() * 1000) + "");

        tianChengDataBackFlowDubboService.projecctStatusChange(projectStatusChangeBackFlowRequestDTO);
    }

	/**
	 * 更新天秤标的状态通知成功
	 * @param projectId
	 */
	@Transactional
	public void updateTianChengProjectStatusNotifySuccessful(Long projectId){
		LendDataNotify lendDataNotify = new LendDataNotify();
		lendDataNotify.setProjectId(projectId);
		lendDataNotify.setTianchengProjectStatus(LendOrderStatusEnum.SUCCESS.getValue());
		lendDataNotifyMapperExt.updateByPrimaryKeySelective(lendDataNotify);
	}

	/**
	 * 天秤数据回流
	 * 
	 * @param project
	 */
	private void repaymentPlanDataFlow(Project project) throws InterruptedException, ExecutionException{
		logger.info("天秤数据回流开始...");
		queryForMaster();
		List<ProjectBorrowerPlanNewDTO> projectBorrowerPlanNewDTOList = projectBorrowerPlanNewMapperExt.selectByProjectIdForAmount(project.getProjectId());

		List<RepaymentPlanRequest.RepaymentPlan> repaymentPlanList = new ArrayList<>();

		for (ProjectBorrowerPlanNewDTO projectBorrowerPlanNewDTO : projectBorrowerPlanNewDTOList) {
			RepaymentPlanRequest.RepaymentPlan repaymentPlan = new RepaymentPlanRequest.RepaymentPlan();
			repaymentPlan.setUserId(projectBorrowerPlanNewDTO.getUserId());
			repaymentPlan.setProjectId(projectBorrowerPlanNewDTO.getProjectId() + "");
			repaymentPlan.setCurrentPeriods(projectBorrowerPlanNewDTO.getPeriod());
			repaymentPlan.setTotalPeriods(projectBorrowerPlanNewDTO.getTotalPeriod());
			repaymentPlan.setCostAmoun(projectBorrowerPlanNewDTO.getCapital());
			repaymentPlan.setRefundInterest(projectBorrowerPlanNewDTO.getInterest());
			repaymentPlan.setRefundDate(projectBorrowerPlanNewDTO.getRefundDate().getTime() * 1000);
			repaymentPlan.setAddDate(projectBorrowerPlanNewDTO.getCreateTime().getTime() * 1000);

			repaymentPlanList.add(repaymentPlan);
		}

		RepaymentPlanRequest request = new RepaymentPlanRequest();
		request.setList(repaymentPlanList);

		dataFlowService.repaymentPlan(request).get();
		logger.info("天秤数据回流结束...");
	}

	/**
	 * 更新天秤回款计划回流通知成功
	 * @param projectId
	 */
	@Transactional
	public void updateTianChengRepaymentPlanNotifySuccessful(Long projectId){
		LendDataNotify lendDataNotify = new LendDataNotify();
		lendDataNotify.setProjectId(projectId);
		lendDataNotify.setTianchengRepaymentPlanStatus(LendOrderStatusEnum.SUCCESS.getValue());
		lendDataNotifyMapperExt.updateByPrimaryKeySelective(lendDataNotify);
	}

	/**
	 * 放款红包处理
	 * 
	 * @param project
	 * @param projectInvestorPlanList
	 */
	private void prizeHandler(Project project, List<ProjectInvestorPlan> projectInvestorPlanList) {
		logger.info("放款红包处理开始...");
		// 借款红包
		try {
			borrowerPrizeHandler(project);
			((ProjectLendLocalService)AopContext.currentProxy()).updateBorrowerPrizeNotifySuccessful(project.getProjectId());
		} catch (Throwable e) {
			logger.error("借款红包处理异常 projectId:{}", project.getProjectId(), e);
		}

		// 投资红包
		investorPrizeHandler(project, projectInvestorPlanList);
		((ProjectLendLocalService)AopContext.currentProxy()).updateAllInvestorPrizeNotifySuccessful(project.getProjectId());
		logger.info("放款红包处理结束...");
	}
	
	/**
	 * 标低运营投资加息活动处理
	 * 
	 * @param project
	 * @param projectInvestOrderList
	 */
	private void projectRaiseRateHandle(Project project, List<ProjectInvestOrder> projectInvestOrderList) {
		try {
			// 判断标的是否关联活动
			if (null != project.getActivityId() && project.getActivityId() > 0) {
				ProjectRaiseRateInvestReqDTO projectRaiseRateInvestReqDTO = new ProjectRaiseRateInvestReqDTO();
				projectRaiseRateInvestReqDTO.setProjectId(project.getProjectId());
				projectRaiseRateInvestReqDTO.setRaiseRateConfigId(project.getActivityId());
				projectRaiseRateInvestReqDTO.setRaiseRate(project.getActivityRaiseRate());
				projectRaiseRateInvestReqDTO.setDeadLine(project.getDeadline());
				projectRaiseRateInvestReqDTO.setDeadLineUnit(Integer.valueOf(project.getDeadlineUnit()));
				projectRaiseRateInvestReqDTO.setProjectRepaymentTypeEnum(transformActivityRepaymentType4Trade(RepaymentTypeEnum.enumOf(project.getRepaymentType())));
				
				// 投资订单列表
				List<ProjectRaiseRateInvestReqDTO.InvestOrderDTO> investOrderDTOList = Lists.newArrayList();
				projectRaiseRateInvestReqDTO.setInvestOrderDTOList(investOrderDTOList);
				for (ProjectInvestOrder projectInvestOrder : projectInvestOrderList) {
					if (!ProjectInvestOrderStatusEnum.SUCCESS.getValue().equals(projectInvestOrder.getStatus())) {
						continue;
					}
					ProjectRaiseRateInvestReqDTO.InvestOrderDTO investOrderDTO = new ProjectRaiseRateInvestReqDTO.InvestOrderDTO();
					investOrderDTO.setInvestOrderId(projectInvestOrder.getId());
					investOrderDTO.setUserId(projectInvestOrder.getUserId());
					investOrderDTO.setAmount(projectInvestOrder.getAmount());
					investOrderDTOList.add(investOrderDTO);
				}

				logger.info("###满标放款###调用活动中心运营标的投资加息活动事件，projectId:{}, 请求参数：{}", project.getProjectId(), JSONObject.toJSONString(projectRaiseRateInvestReqDTO));
				projectRaiseRateDubboService.createProjectRaiseRatePlan(projectRaiseRateInvestReqDTO);
			}
			
			logger.info("###满标放款###调用活动中心运营标的投资加息活动事件成功，更新通知记录状态，projectId:{}", project.getProjectId());
			((ProjectLendLocalService) AopContext.currentProxy()).updateRaiseRateNotifySuccessful(project.getProjectId());
		} catch (Exception e) {
			 logger.error("###满标放款###调用活动中心运营标的投资加息活动事件异常，projectId:{}", project.getProjectId(), e);
		}
	}

	/**
	 * 包运营投资加息活动处理
	 *
	 * @param project
	 * @param projectInvestOrderList
	 */
	private void packageRaiseRateHandle(Project project, List<ProjectInvestOrder> projectInvestOrderList) {
		queryForMaster();
		Long packageId = projectPackageDetailMapperExt.selectPackageIdByProjectId(project.getProjectId());
		if(packageId == null){
			((ProjectLendLocalService) AopContext.currentProxy()).updatePackageRaiseRateNotifySuccessful(project.getProjectId());
			return;
		}
		ProjectPackage projectPackage = projectPackageMapperExt.selectByPrimaryKey(packageId);
		try {
			// 判断包是否有活动加息
			if (null != projectPackage.getActivityRaiseRate() && projectPackage.getActivityRaiseRate().compareTo(BigDecimal.ZERO) > 0) {
				ProjectRaiseRateInvestReqDTO projectRaiseRateInvestReqDTO = new ProjectRaiseRateInvestReqDTO();
				projectRaiseRateInvestReqDTO.setProjectId(project.getProjectId());
				//projectRaiseRateInvestReqDTO.setRaiseRateConfigId(project.getActivityId());
				projectRaiseRateInvestReqDTO.setRaiseRate(projectPackage.getActivityRaiseRate());
				projectRaiseRateInvestReqDTO.setDeadLine(project.getDeadline());
				projectRaiseRateInvestReqDTO.setDeadLineUnit(Integer.valueOf(project.getDeadlineUnit()));
				projectRaiseRateInvestReqDTO.setProjectRepaymentTypeEnum(transformActivityRepaymentType4Trade(RepaymentTypeEnum.enumOf(project.getRepaymentType())));

				// 投资订单列表
				List<ProjectRaiseRateInvestReqDTO.InvestOrderDTO> investOrderDTOList = Lists.newArrayList();
				projectRaiseRateInvestReqDTO.setInvestOrderDTOList(investOrderDTOList);
				for (ProjectInvestOrder projectInvestOrder : projectInvestOrderList) {
					if (!ProjectInvestOrderStatusEnum.SUCCESS.getValue().equals(projectInvestOrder.getStatus())) {
						continue;
					}
					ProjectRaiseRateInvestReqDTO.InvestOrderDTO investOrderDTO = new ProjectRaiseRateInvestReqDTO.InvestOrderDTO();
					investOrderDTO.setInvestOrderId(projectInvestOrder.getId());
					investOrderDTO.setUserId(projectInvestOrder.getUserId());
					investOrderDTO.setAmount(projectInvestOrder.getAmount());
					investOrderDTOList.add(investOrderDTO);
				}

				logger.info("###满标放款###调用活动中心包运营投资加息活动事件，projectId:{},packageId:{},请求参数：{}", project.getProjectId(), packageId, JSONObject.toJSONString(projectRaiseRateInvestReqDTO));
				projectRaiseRateDubboService.createProjectRaiseRatePlan(projectRaiseRateInvestReqDTO);
			}

			logger.info("###满标放款###调用活动中心包运营投资加息活动事件成功，更新通知记录状态，projectId:{},packageId:{}", project.getProjectId(), packageId);
			((ProjectLendLocalService) AopContext.currentProxy()).updatePackageRaiseRateNotifySuccessful(project.getProjectId());
		} catch (Exception e) {
			logger.error("###满标放款###调用活动中心包运营投资加息活动事件异常，projectId:{},packageId:{}", project.getProjectId(), packageId, e);
		}
	}

	/**
	 * 投资人红包处理
	 * @param project
	 * @param projectInvestorPlanList
	 */
	private void investorPrizeHandler(Project project, List<ProjectInvestorPlan> projectInvestorPlanList) {
		List<ProjectInvestOrder> projectInvestOrderList = projectInvestOrderMapperExt
				.queryProjectInvestOrderListOrderByCreateTimeAscByProjectId(project.getProjectId());
		for (ProjectInvestOrder projectInvestOrder : projectInvestOrderList) {
			if (projectInvestOrder != null
					&& ProjectInvestOrderStatusEnum.SUCCESS.getValue().equals(projectInvestOrder.getStatus())
					&& projectInvestOrder.getPrizeId() != null) {
				logger.info("investorPrizeHandler investOrderId:{}, prizeId:{}", projectInvestOrder.getId(), projectInvestOrder.getPrizeId());
				investorPrizeHandler(project, projectInvestorPlanList, projectInvestOrder);
			}
		}
	}

	/**
	 *  投资红包处理
	 * @param project
	 * @param projectInvestorPlanList
	 * @param projectInvestOrder
	 */
	private void investorPrizeHandler(Project project, List<ProjectInvestorPlan> projectInvestorPlanList, ProjectInvestOrder projectInvestOrder) {
		try {
            UserPrizeResponseDTO userPrizeResponseDTO = activityPrizeDubboService.getUserPrizeInfo(
                    projectInvestOrder.getUserId(), projectInvestOrder.getPrizeId());

            if (userPrizeResponseDTO != null) {
                logger.info("investorPrizeHandler investOrderId:{}, prizeId:{}, userPrizeResponseDTO：{}", projectInvestOrder.getId(), projectInvestOrder.getPrizeId(), JSON.toJSON(userPrizeResponseDTO));
                if (UserPrizeTypeIdEnum.INVESTMENT_RAISE_INTEREST_RATES.getPrizeType().equals(
                        userPrizeResponseDTO.getPrizeTypeId())) {//投资加息券
                    ActiveInerestRateReqDTO requestDTO = new ActiveInerestRateReqDTO();
                    requestDTO.setInvestOrderId(projectInvestOrder.getId());
                    requestDTO.setPrizeId(projectInvestOrder.getPrizeId());// 红包id：必传。
                    requestDTO.setUserId(projectInvestOrder.getUserId());
                    requestDTO.setDeadLine(project.getDeadline());// 借款期限：必传
					requestDTO.setDeadLineUnit(PeriodUnitEnum.DAY.equals(PeriodUnitEnum.enumOf(project.getDeadlineUnit())) ? 1 : 0);// 借款期限单位 0:月; 1:天;
					requestDTO.setProjectRepaymentTypeEnum(transformActivityRepaymentType4Trade(RepaymentTypeEnum.enumOf(project.getRepaymentType()))); // 还款方式
					
                    // 回款期数与本金
                    Map<Integer, BigDecimal> investCapitalMap = new HashMap<>();
                    requestDTO.setInvestCapitalMap(investCapitalMap);
                    for (ProjectInvestorPlan projectInvestorPlan : projectInvestorPlanList) {
                        if (projectInvestorPlan != null && projectInvestOrder.getId().equals(projectInvestorPlan.getInvestOrderId())) {
                            investCapitalMap.put(projectInvestorPlan.getCurrentPeriod(), projectInvestorPlan.getCapital());
                        }
                    }

                    logger.info("investorPrizeHandler activeInterestRatePrize investOrderId:{}, prizeId:{}, requestDTO : {}", projectInvestOrder.getId(), projectInvestOrder.getPrizeId(), JSON.toJSON(requestDTO));
                    activityPrizeDubboService.activeInterestRatePrize(requestDTO);
                } else if (UserPrizeTypeIdEnum.INVESTMENT_CASHBACK.getPrizeType().equals(
                        userPrizeResponseDTO.getPrizeTypeId())) {// 投资返现红包
                    ActiveInvestorCashBackReqDTO requestDTO = new ActiveInvestorCashBackReqDTO();
                    requestDTO.setInvestOrderId(projectInvestOrder.getId());
                    requestDTO.setPrizeId(projectInvestOrder.getPrizeId());
                    requestDTO.setUserId(projectInvestOrder.getUserId());
                    logger.info("investorPrizeHandler activeInvestorCashBackPrize investOrderId:{}, prizeId:{}, requestDTO:{}", projectInvestOrder.getId(), projectInvestOrder.getPrizeId(), JSON.toJSON(requestDTO));
                    activityPrizeDubboService.activeInvestorCashBackPrize(requestDTO);
                }
            } else {
                logger.warn("investorPrizeHandler userPrizeResponseDTO is null investOrderId:{}, prizeId:{}", projectInvestOrder.getId(), projectInvestOrder.getPrizeId());
            }
            ((ProjectLendLocalService)AopContext.currentProxy()).updateInvestorPrizeNotifySuccessful(projectInvestOrder.getId());
        } catch (Throwable e) {
            logger.error("投资红包处理异常", e);
        }
	}

	/**
	 * 借款人红包处理
	 * @param project
	 */
	private void borrowerPrizeHandler(Project project) {
		if (project.getPrizeId() != null && project.getPrizeId() != 0) {
			logger.info("borrowerPrizeHandler projectId:{}, PrizeId：{}", project.getProjectId(), project.getPrizeId());
			UserPrizeResponseDTO userPrizeResponseDTO = activityPrizeDubboService.getUserPrizeInfo(
					project.getBorrowUserId(), project.getPrizeId());
			if (userPrizeResponseDTO != null) {
				logger.info("borrowerPrizeHandler projectId:{}, userPrizeResponseDTO：{}", project.getProjectId(), JSON.toJSON(userPrizeResponseDTO));
				if (UserPrizeTypeIdEnum.LOAN_CASHBACK.getPrizeType().equals(userPrizeResponseDTO.getPrizeTypeId())) {
					// 11借款返现红包
					ActiveLoanCashBackReqDTO requestDTO = new ActiveLoanCashBackReqDTO();
					requestDTO.setPrizeId(project.getPrizeId());
					requestDTO.setUserId(project.getBorrowUserId());
					logger.info("borrowerPrizeHandler projectId:{}, activeLoancashBackPrize requestDTO : {}", project.getProjectId(), JSON.toJSON(requestDTO));
					activityPrizeDubboService.activeLoancashBackPrize(requestDTO);
				} else if (UserPrizeTypeIdEnum.BORROW_INTEREST_RATE_DISCOUNT.getPrizeType().equals(
						userPrizeResponseDTO.getPrizeTypeId())) {
					// 12借款利率折扣卡
					ActiveInerestDiscountBackReqDTO requestDTO = new ActiveInerestDiscountBackReqDTO();
					requestDTO.setDeadLine(project.getDeadline());
					requestDTO.setDeadLineUnit(PeriodUnitEnum.DAY.equals(PeriodUnitEnum.enumOf(project
							.getDeadlineUnit())) ? 1 : 0);
					requestDTO.setPrizeId(project.getPrizeId());
					requestDTO.setUserId(project.getBorrowUserId());
					// (期数，还款利息):必传
					Map<Integer, BigDecimal> borrowerInterestMap = new HashMap<>();

					// 主库查询设置
					queryForMaster();

					List<ProjectBorrowerPlanNewDTO> projectBorrowerPlanNewDTOList = projectBorrowerPlanNewMapperExt.selectByProjectIdForAmount(project.getProjectId());
					for (ProjectBorrowerPlanNewDTO projectBorrowerPlanNewDTO : projectBorrowerPlanNewDTOList) {
						if (projectBorrowerPlanNewDTO != null) {
							borrowerInterestMap.put(projectBorrowerPlanNewDTO.getPeriod(),
									projectBorrowerPlanNewDTO.getInterest());
						}
					}

					requestDTO.setBorrowerInterestMap(borrowerInterestMap);
					logger.info("borrowerPrizeHandler projectId:{}, activeInterestDiscountPrize requestDTO : {}", project.getProjectId(), JSON.toJSON(requestDTO));
					activityPrizeDubboService.activeInterestDiscountPrize(requestDTO);
				}
			} else {
				logger.warn("borrowerPrizeHandler userPrizeResponseDTO is null projectId:{}, PrizeId：{}", project.getProjectId(), project.getPrizeId());
			}
		}
	}

	/**
	 * 更新借款红包通知成功
	 * @param projectId
	 */
	@Transactional
	public void updateBorrowerPrizeNotifySuccessful(Long projectId){
		LendDataNotify lendDataNotify = new LendDataNotify();
		lendDataNotify.setProjectId(projectId);
		lendDataNotify.setBorrowerPrizeStatus(LendOrderStatusEnum.SUCCESS.getValue());
		lendDataNotifyMapperExt.updateByPrimaryKeySelective(lendDataNotify);
	}

	/**
	 * 更新投资红包通知成功
	 * @param investOrderId
	 */
	@Transactional
	public void updateInvestorPrizeNotifySuccessful(Long investOrderId){
		LendInvestPrizeNotify lendInvestPrizeNotify = new LendInvestPrizeNotify();
		lendInvestPrizeNotify.setInvestOrderId(investOrderId);
		lendInvestPrizeNotify.setStatus(LendOrderStatusEnum.SUCCESS.getValue());
		lendInvestPrizeNotifyMapperExt.updateByPrimaryKeySelective(lendInvestPrizeNotify);
	}

	/**
	 * 更新所有投资红包通知成功
	 * @param projectId
	 */
	@Transactional
	public void updateAllInvestorPrizeNotifySuccessful(Long projectId){
		Integer notSuccessNum = lendInvestPrizeNotifyMapperExt.queryInvestPrizeNotifyNotSuccessNumByProjectId(projectId);
		// 全部成功后更新所有投资红包通知成功
		if(notSuccessNum == 0) {
			LendDataNotify lendDataNotify = new LendDataNotify();
			lendDataNotify.setProjectId(projectId);
			lendDataNotify.setInvestorPrizeStatus(LendOrderStatusEnum.SUCCESS.getValue());
			lendDataNotifyMapperExt.updateByPrimaryKeySelective(lendDataNotify);
		}
	}

	/**
	 * 更新运营投资加息活动通知成功
	 * 
	 * @param projectId
	 */
	@Transactional
	public void updateRaiseRateNotifySuccessful(Long projectId){
		LendDataNotify lendDataNotify = new LendDataNotify();
		lendDataNotify.setProjectId(projectId);
		lendDataNotify.setRaiseRateStatus(LendOrderStatusEnum.SUCCESS.getValue());
		lendDataNotify.setUpdateTime(new Date());
		lendDataNotifyMapperExt.updateByPrimaryKeySelective(lendDataNotify);
	}

	/**
	 * 更新运营投资加息活动通知成功
	 *
	 * @param projectId
	 */
	@Transactional
	public void updatePackageRaiseRateNotifySuccessful(Long projectId){
		LendDataNotify lendDataNotify = new LendDataNotify();
		lendDataNotify.setProjectId(projectId);
		lendDataNotify.setPackageRaiseRateStatus(LendOrderStatusEnum.SUCCESS.getValue());
		lendDataNotify.setUpdateTime(new Date());
		lendDataNotifyMapperExt.updateByPrimaryKeySelective(lendDataNotify);
	}

	/**
	 * 发送通知
	 *
	 * @param projectId
	 */
	private void sendMessageAndStandLetter(Long projectId) {
		Project project = projectMapperExt.selectByPrimaryKey(projectId);
		LendSuccessBorrowerNotifyDTO lendSuccessBorrowerNotifyDTO = new LendSuccessBorrowerNotifyDTO();
		lendSuccessBorrowerNotifyDTO.setUserId(project.getBorrowUserId());
		lendSuccessBorrowerNotifyDTO.setProjectId(projectId);
		lendSuccessBorrowerNotifyDTO.setProjectTitle(project.getTitle());
		// 自动提现消息
		if(project.getType().equals(BorrowProjectTypeEnum.SMALL_LOAN.getValue())
				|| project.getType().equals(BorrowProjectTypeEnum.SOCIAL_SECURITY_LOAN.getValue())
				|| project.getType().equals(BorrowProjectTypeEnum.CREDIT_CARD_LOAN.getValue())
				|| project.getType().equals(BorrowProjectTypeEnum.CONSUME_LOAN.getValue())) {
			LendOrder lendOrder = lendOrderMapperExt.selectByPrimaryKey(projectId);
			WithdrawOrderResponseDTO withdrawOrderResponseDTO = withdrawDubboService.getWithdrawOrderById(lendOrder.getWithdrawOrderId());

			if(withdrawOrderResponseDTO != null){
				lendSuccessBorrowerNotifyDTO.setBorrowAmount(project.getContractAmount());
				lendSuccessBorrowerNotifyDTO.setWithdrawFee(withdrawOrderResponseDTO.getRealFee());
				lendSuccessBorrowerNotifyDTO.setRealAmount(withdrawOrderResponseDTO.getRealAmount());
			}
		}
		lendSuccessBorrowerNotifyDTO.setH5BorrowDetailUrl(h5BorrowDetailUrl);

		List<LendSuccessInvestorNotifyDTO> lendSuccessInvestorNotifyDTOList = new ArrayList<>();

		List<ProjectInvestOrder> projectInvestOrderList = projectInvestOrderMapperExt
				.queryProjectInvestOrderListOrderByCreateTimeAscByProjectId(project.getProjectId());
		for (ProjectInvestOrder projectInvestOrder : projectInvestOrderList) {
			if (projectInvestOrder != null
					&& ProjectInvestOrderStatusEnum.SUCCESS.getValue().equals(projectInvestOrder.getStatus())) {

				LendSuccessInvestorNotifyDTO investLendSuccessDTO = new LendSuccessInvestorNotifyDTO();
				investLendSuccessDTO.setUserId(projectInvestOrder.getUserId());
				investLendSuccessDTO.setInvestOrderId(projectInvestOrder.getId());
				investLendSuccessDTO.setProjectId(projectId);
				investLendSuccessDTO.setProjectTitle(project.getTitle());
				investLendSuccessDTO.setH5InvestDetailUrl(h5InvestDetailUrl);

				lendSuccessInvestorNotifyDTOList.add(investLendSuccessDTO);
			}
		}

		LendSuccessNotifyDTO lendSuccessNotifyDTO = new LendSuccessNotifyDTO();
		lendSuccessNotifyDTO.setLendSuccessBorrowerNotifyDTO(lendSuccessBorrowerNotifyDTO);
		lendSuccessNotifyDTO.setLendSuccessInvestorNotifyDTOList(lendSuccessInvestorNotifyDTOList);
		lendSuccessNotifyDTO.setIsPackagedProject(projectPackageLocalService.isPackagedProject(project.getProjectId()));

		messageSendDubboService.sendNotfyForLendSuccess(lendSuccessNotifyDTO);
	}

	/**
	 * 根据标的id查询放款订单
	 *
	 * @param projectId
	 * @return
	 */
	public LendOrder queryLendOrderByProjectId(Long projectId) {
		this.queryForMaster();
		return lendOrderMapperExt.selectByPrimaryKey(projectId);
	}

	public void bankLendResultQueryJob() {
		logger.info("银行放款结果查询...");
		List<LendOrderDetail> lendOrderDetailList = lendOrderDetailMapperExt.queryLendOrderDetailByBankLendResultQueryJob();
		if(lendOrderDetailList != null){
			for (LendOrderDetail lendOrderDetail : lendOrderDetailList) {
				if (lendOrderDetail != null) {
					logger.info("银行放款结果查询 lendOrderDetail:{}", JSON.toJSON(lendOrderDetail));
					try {
						BathTransactionNotifyDTO bathTransactionNotifyDTO = queryBankLendResult(lendOrderDetail.getDetailRequestNo(), lendOrderDetail.getProjectId());
						((ProjectLendLocalService)AopContext.currentProxy()).lendResultNotify(bathTransactionNotifyDTO);
					} catch (Throwable e) {
						logger.error("银行放款结果查询执行异常 lendOrderDetail:{}", JSON.toJSON(lendOrderDetail), e);
					}
				}
			}
		}
	}

	public void bankLendFailedJob() {
		logger.info("银行放款失败任务...");
		List<LendOrderDetail> lendOrderDetailList = lendOrderDetailMapperExt.queryLendOrderDetailByBankLendFailedJob();
		if(lendOrderDetailList != null){
			for (LendOrderDetail lendOrderDetail : lendOrderDetailList) {
				if (lendOrderDetail != null) {
					logger.info("银行放款失败任务 lendOrderDetail:{}", JSON.toJSON(lendOrderDetail));
					try {
                        ((ProjectLendLocalService)AopContext.currentProxy()).bankLendFailed(lendOrderDetail.getProjectId());
					} catch (Throwable e) {
						logger.error("银行放款失败任务执行异常 lendOrderDetail:{}", JSON.toJSON(lendOrderDetail), e);
					}
				}
			}
		}
	}

	@Transactional
	public void bankLendFailed(Long projectId){
	    // 根据标的ID查询出该标的失败的放款明细
		logger.info("银行放款失败修改订单，重新发起放款 projectId:{}", projectId);
		List<LendOrderDetail> failedLendOrderDetailList = lendOrderDetailMapperExt.queryFailedLendOrderDetailByProjectId(projectId);
		if(failedLendOrderDetailList.isEmpty()){
		    return;
        }
        List<AsyncTransactionRequest.BizDetail> bizDetailList = new ArrayList<>();
        String newBatchNo = lanMaoSequence.getBatchNo();
		for (LendOrderDetail lendOrderDetail : failedLendOrderDetailList) {
			List<LendOrderDetailBiz> lendOrderDetailBizList = lendOrderDetailBizMapperExt.queryLendOrderDetailBizByDetailRequestNo(lendOrderDetail.getDetailRequestNo());

            String newDetailRequestNo = lanMaoSequence.getRequestNo();

            AsyncTransactionRequest.BizDetail bizDetail = new AsyncTransactionRequest.BizDetail();
			bizDetail.setRequestNo(newDetailRequestNo);
			bizDetail.setTradeType(TransactionTypeEnum.TENDER);
			bizDetail.setProjectNo(lendOrderDetail.getProjectId() + "");
			List<AsyncTransactionRequest.BizDetail.BusinessDetail> businessDetailList = new ArrayList<>();

			for (LendOrderDetailBiz lendOrderDetailBiz : lendOrderDetailBizList) {
				AsyncTransactionRequest.BizDetail.BusinessDetail businessDetail = new AsyncTransactionRequest.BizDetail.BusinessDetail();
				BusinessTypeEnum bizType = BusinessTypeEnum.enumOf(lendOrderDetailBiz.getBizType());
				businessDetail.setBizType(bizType);
				businessDetail.setFreezeRequestNo(lendOrderDetailBiz.getFreezeRequestNo());
				businessDetail.setSourcePlatformUserNo(lendOrderDetailBiz.getSourcePlatformUserNo());
				businessDetail.setTargetPlatformUserNo(lendOrderDetailBiz.getTargetPlatformUserNo());
				businessDetail.setAmount(lendOrderDetailBiz.getAmount());
                businessDetailList.add(businessDetail);

				// 修改原业务明细存管流水号
                LendOrderDetailBiz updateLendOrderDetailBiz = new LendOrderDetailBiz();
                updateLendOrderDetailBiz.setId(lendOrderDetailBiz.getId());
                updateLendOrderDetailBiz.setDetailRequestNo(newDetailRequestNo);
                lendOrderDetailBizMapperExt.updateByPrimaryKeySelective(updateLendOrderDetailBiz);
			}
            bizDetail.setDetails(businessDetailList);
            bizDetailList.add(bizDetail);

            // 修改原放款明细存管流水号、批次号和状态
            LendOrderDetail updateLendOrderDetail = new LendOrderDetail();
            updateLendOrderDetail.setId(lendOrderDetail.getId());
            updateLendOrderDetail.setBatchNo(newBatchNo);
            updateLendOrderDetail.setDetailRequestNo(newDetailRequestNo);
            updateLendOrderDetail.setStatus(LendOrderStatusEnum.HANDLING.getValue());
            lendOrderDetailMapperExt.updateByPrimaryKeySelective(updateLendOrderDetail);
		}

        // 修改原放款订单批次号和状态
		LendOrder updateLendOrder = new LendOrder();
        updateLendOrder.setProjectId(projectId);
        updateLendOrder.setBatchNo(newBatchNo);
        updateLendOrder.setStatus(LendOrderStatusEnum.HANDLING.getValue());
        lendOrderMapperExt.updateByPrimaryKeySelective(updateLendOrder);

        // 银行存管业务明细
        AsyncTransactionRequest asyncTransactionRequest = new AsyncTransactionRequest();
        asyncTransactionRequest.setBatchNo(newBatchNo);
        asyncTransactionRequest.setBizDetails(bizDetailList);
        logger.info("银行放款失败修改订单，重新发起放款 放款订单构建成功 projectId:{}, asyncTransactionRequest:{}", projectId, JSON.toJSON(asyncTransactionRequest));

        //调用银行存管放款
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCommit() {
                super.afterCommit();
                // 调用银行存管放款
                callBankLend(asyncTransactionRequest);
            }
        });
	}

	public void bankProjectStatusJob() {
		logger.info("银行标的状态变更失败任务...");
		List<LendOrder> lendOrderList = lendOrderMapperExt.queryLendOrderByBankProjectStatusJob();
		ProjectLendLocalService projectLendLocalService = ((ProjectLendLocalService)AopContext.currentProxy());
		if(lendOrderList != null){
			for (LendOrder lendOrder : lendOrderList) {
				if (lendOrder != null) {
					logger.info("银行标的状态变更失败任务 lendOrder:{}", JSON.toJSON(lendOrder));
					try {
						projectLendLocalService.updateProjectStatus(lendOrder.getProjectId());
					} catch (Throwable e) {
						logger.error("银行标的状态变更失败任务执行异常 lendOrder:{}", JSON.toJSON(lendOrder), e);
					}
				}
			}
		}
	}

	public void accountingStatusJob() {
		logger.info("记账任务...");
		List<LendOrder> lendOrderList = lendOrderMapperExt.queryLendOrderByAccountingStatusJob();
		if(lendOrderList != null){
			for (LendOrder lendOrder : lendOrderList) {
				if (lendOrder != null) {
					logger.info("记账任务 lendOrder:{}", JSON.toJSON(lendOrder));
					try {
						Project project = projectMapperExt.selectByPrimaryKey(lendOrder.getProjectId());
						List<ProjectInvestorPlan> projectInvestorPlanList = projectInvestorPlanMapperExt.queryProjectInvestorPlanByProjectId(lendOrder.getProjectId());
						lendSuccessAccounting(project, projectInvestorPlanList);
					} catch (Throwable e) {
						logger.error("记账任务执行异常 lendOrder:{}", JSON.toJSON(lendOrder), e);
					}
				}
			}
		}
	}

	public void investRankStatusJob() {
		logger.info("投资排行榜任务...");
		List<LendDataNotify> lendDataNotifieList = lendDataNotifyMapperExt.queryLendDataNotifyByInvestRankStatusJob();
		if(lendDataNotifieList != null){
			for (LendDataNotify lendDataNotify : lendDataNotifieList) {
				if (lendDataNotify != null) {
					logger.info("投资排行榜任务 lendDataNotify:{}", JSON.toJSON(lendDataNotify));
					try {
						investRankNotify(lendDataNotify.getProjectId());
						((ProjectLendLocalService)AopContext.currentProxy()).updateInvestRankNotifySuccessful(lendDataNotify.getProjectId());
					} catch (Throwable e) {
						logger.error("投资排行榜任务执行异常 lendDataNotify:{}", JSON.toJSON(lendDataNotify), e);
					}
				}
			}
		}
	}

	public void borrowerPrizeStatusJob() {
		logger.info("借款人红包任务...");
		List<LendDataNotify> lendDataNotifieList = lendDataNotifyMapperExt.queryLendDataNotifyByBorrowerPrizeStatusJob();
		if(lendDataNotifieList != null){
			for (LendDataNotify lendDataNotify : lendDataNotifieList) {
				if (lendDataNotify != null) {
					logger.info("借款人红包任务 lendDataNotify:{}", JSON.toJSON(lendDataNotify));
					try {
						Project project = projectMapperExt.selectByPrimaryKey(lendDataNotify.getProjectId());
						borrowerPrizeHandler(project);
                        ((ProjectLendLocalService) AopContext.currentProxy()).updateBorrowerPrizeNotifySuccessful(project.getProjectId());
					} catch (Throwable e) {
						logger.error("借款人红包任务执行异常 lendDataNotify:{}", JSON.toJSON(lendDataNotify), e);
					}
				}
			}
		}
	}

	public void investorPrizeStatusJob() {
		logger.info("投资人红包任务...");
		List<LendInvestPrizeNotify> lendInvestPrizeNotifyList = lendInvestPrizeNotifyMapperExt.queryInvestPrizeNotifyByInvestorPrizeStatusJob();
		if(lendInvestPrizeNotifyList != null){
			for (LendInvestPrizeNotify lendInvestPrizeNotify : lendInvestPrizeNotifyList) {
				if (lendInvestPrizeNotify != null) {
					logger.info("投资人红包任务 lendInvestPrizeNotify:{}", JSON.toJSON(lendInvestPrizeNotify));
					try {
						Project project = projectMapperExt.selectByPrimaryKey(lendInvestPrizeNotify.getProjectId());
						ProjectInvestOrder projectInvestOrder = projectInvestOrderMapperExt.selectByPrimaryKey(lendInvestPrizeNotify.getInvestOrderId());
						List<ProjectInvestorPlan> projectInvestorPlanList = projectInvestorPlanMapperExt.queryProjectInvestorPlanByProjectId(lendInvestPrizeNotify.getProjectId());
						investorPrizeHandler(project, projectInvestorPlanList, projectInvestOrder);
                        ((ProjectLendLocalService)AopContext.currentProxy()).updateAllInvestorPrizeNotifySuccessful(lendInvestPrizeNotify.getProjectId());
					} catch (Throwable e) {
						logger.error("投资人红包任务执行异常 lendInvestPrizeNotify:{}", JSON.toJSON(lendInvestPrizeNotify), e);
					}
				}
			}
		}
	}
	
	/**
	 * 标运营投资加息活动处理补偿任务
	 */
	public void projectRaiseRateStatusJob() {
		logger.info("###满标放款###标运营投资加息活动通知补偿任务开始");
		Long beginTime = System.currentTimeMillis();
		List<LendDataNotify> lendDataNotifyList = lendDataNotifyMapperExt.queryLendDataNotifyByRaiseRateStatusJob();
		if (null == lendDataNotifyList || lendDataNotifyList.size() == 0) {
			logger.info("###满标放款###标运营投资加息活动通知补偿任务，本次待处理记录为空，任务结束，共耗时：{}mm", System.currentTimeMillis() - beginTime);
			return;
		}
		logger.info("###满标放款###标运营投资加息活动通知补偿任务，本次待处理记录的总数：{}", lendDataNotifyList.size());
		for (LendDataNotify lendDataNotify : lendDataNotifyList) {
			Project project = projectMapperExt.selectByPrimaryKey(lendDataNotify.getProjectId());
			if (null == project) {
				logger.error("###满标放款###标运营投资加息活动通知补偿任务，标的不存在， ProjectId:{}", lendDataNotify.getProjectId());
				continue;
			}
			List<ProjectInvestOrder> projectInvestOrderList = projectInvestOrderMapperExt.queryProjectInvestOrderListOrderByCreateTimeAscByProjectId(project.getProjectId());
			if (null == projectInvestOrderList || projectInvestOrderList.size() == 0) {
				logger.error("###满标放款###标运营投资加息活动通知补偿任务，投资订单不存在， ProjectId:{}", lendDataNotify.getProjectId());
				continue;
			}
			projectRaiseRateHandle(project, projectInvestOrderList);
		}
		logger.info("###满标放款###标运营投资加息活动通知补偿任务结束， 共耗时:{}mm", System.currentTimeMillis() - beginTime);
	}

	/**
	 * 运营投资加息活动处理补偿任务
	 */
	public void packageRaiseRateStatusJob() {
		logger.info("###满标放款###包运营投资加息活动通知补偿任务开始");
		Long beginTime = System.currentTimeMillis();
		List<LendDataNotify> lendDataNotifyList = lendDataNotifyMapperExt.queryLendDataNotifyByPackageRaiseRateStatusJob();
		if (null == lendDataNotifyList || lendDataNotifyList.size() == 0) {
			return;
		}
		logger.info("###满标放款###包运营投资加息活动通知补偿任务，本次待处理记录的总数：{}", lendDataNotifyList.size());
		for (LendDataNotify lendDataNotify : lendDataNotifyList) {
			Project project = projectMapperExt.selectByPrimaryKey(lendDataNotify.getProjectId());
			List<ProjectInvestOrder> projectInvestOrderList = projectInvestOrderMapperExt.queryProjectInvestOrderListOrderByCreateTimeAscByProjectId(project.getProjectId());
			packageRaiseRateHandle(project, projectInvestOrderList);
		}
		logger.info("###满标放款###包运营投资加息活动通知补偿任务结束， 共耗时:{}mm", System.currentTimeMillis() - beginTime);
	}
	
	public ProjectRepaymentTypeEnum transformActivityRepaymentType4Trade(RepaymentTypeEnum repaymentTypeEnum) {
		ProjectRepaymentTypeEnum projectRepaymentTypeEnum = ProjectRepaymentTypeEnum.AVERAGE_CAPITAL_PLUS_INTEREST;
		switch (repaymentTypeEnum) {
			case REPAY_PRINCIPAL_INTEREST_AT_TERM:
				projectRepaymentTypeEnum = ProjectRepaymentTypeEnum.REPAY_PRINCIPAL_INTEREST_AT_TERM;
				break;
			case AVERAGE_CAPITAL_PLUS_INTEREST:
				projectRepaymentTypeEnum = ProjectRepaymentTypeEnum.AVERAGE_CAPITAL_PLUS_INTEREST;
				break;
			case MONTHLY_INTEREST_PAYMENT_DUE:
				projectRepaymentTypeEnum = ProjectRepaymentTypeEnum.REPAY_PRINCIPAL_AT_TERM;
				break;
			default:
				break;
		}
		return projectRepaymentTypeEnum;
	}	

	/**
	 * 查询主库设置
	 */
	private void queryForMaster() {
		if (!HintManagerHolder.isMasterRouteOnly()) {
			HintManager hintManager = HintManager.getInstance();
			hintManager.setMasterRouteOnly();
		}
	}
}